diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/internal/KeyboardIconsSet.java b/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/internal/KeyboardIconsSet.java index ac6c37f55..5e2430a4f 100644 --- a/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/internal/KeyboardIconsSet.java +++ b/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/internal/KeyboardIconsSet.java @@ -52,6 +52,7 @@ public final class KeyboardIconsSet { public static final String NAME_PREVIOUS_KEY = "previous_key"; public static final String NAME_TAB_KEY = "tab_key"; public static final String NAME_SHORTCUT_KEY = "shortcut_key"; + public static final String NAME_CLIPBOARD_KEY = "clipboard_key"; public static final String NAME_INCOGNITO_KEY = "incognito_key"; public static final String NAME_SHORTCUT_KEY_DISABLED = "shortcut_key_disabled"; public static final String NAME_LANGUAGE_SWITCH_KEY = "language_switch_key"; @@ -80,6 +81,7 @@ public final class KeyboardIconsSet { NAME_PREVIOUS_KEY, R.styleable.Keyboard_iconPreviousKey, NAME_TAB_KEY, R.styleable.Keyboard_iconTabKey, NAME_SHORTCUT_KEY, R.styleable.Keyboard_iconShortcutKey, + NAME_CLIPBOARD_KEY, R.styleable.Keyboard_iconClipboardKey, NAME_INCOGNITO_KEY, R.styleable.Keyboard_iconIncognitoKey, NAME_SPACE_KEY_FOR_NUMBER_LAYOUT, R.styleable.Keyboard_iconSpaceKeyForNumberLayout, NAME_SHIFT_KEY_SHIFTED, R.styleable.Keyboard_iconShiftKeyShifted, diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/LatinIME.java b/app/src/main/java/org/dslul/openboard/inputmethod/latin/LatinIME.java index 4e2f52edf..1285380d0 100644 --- a/app/src/main/java/org/dslul/openboard/inputmethod/latin/LatinIME.java +++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/LatinIME.java @@ -1117,6 +1117,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } } + public CharSequence getSelection() { + return mInputLogic.mConnection.getSelectedText(0); + } + /** * This is called when the user has clicked on the extracted text view, * when running in fullscreen mode. The default implementation hides @@ -1584,10 +1588,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen currentSettingsValues.mInputAttributes.mShouldShowSuggestions && currentSettingsValues.isSuggestionsEnabledPerUserSettings(); final boolean shouldShowSuggestionsStripUnlessPassword = currentSettingsValues.mShowsVoiceInputKey + || currentSettingsValues.mShowsClipboardKey || shouldShowSuggestionCandidates || currentSettingsValues.isApplicationSpecifiedCompletionsOn(); final boolean shouldShowSuggestionsStrip = shouldShowSuggestionsStripUnlessPassword - && !currentSettingsValues.mInputAttributes.mIsPasswordField; + && (!currentSettingsValues.mInputAttributes.mIsPasswordField || currentSettingsValues.mShowsClipboardKey); mSuggestionStripView.updateVisibility(shouldShowSuggestionsStrip, isFullscreenMode()); if (!shouldShowSuggestionsStrip) { return; diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/Settings.java b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/Settings.java index 3b1d47b06..6522d5d7e 100644 --- a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/Settings.java +++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/Settings.java @@ -56,6 +56,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang // PREF_VOICE_MODE_OBSOLETE is obsolete. Use PREF_VOICE_INPUT_KEY instead. public static final String PREF_VOICE_MODE_OBSOLETE = "voice_mode"; public static final String PREF_VOICE_INPUT_KEY = "pref_voice_input_key"; + public static final String PREF_CLIPBOARD_CLIPBOARD_KEY = "pref_clipboard_clipboard_key"; public static final String PREF_EDIT_PERSONAL_DICTIONARY = "edit_personal_dictionary"; // PREF_AUTO_CORRECTION_THRESHOLD_OBSOLETE is obsolete. Use PREF_AUTO_CORRECTION instead. public static final String PREF_AUTO_CORRECTION_THRESHOLD_OBSOLETE = @@ -77,6 +78,8 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang "pref_show_language_switch_key"; public static final String PREF_SHOW_EMOJI_KEY = "pref_show_emoji_key"; + public static final String PREF_SHOW_CLIPBOARD_KEY = + "pref_show_clipboard_key"; public static final String PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST = "pref_include_other_imes_in_language_switch_list"; public static final String PREF_CUSTOM_INPUT_STYLES = "custom_input_styles"; diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/SettingsValues.java b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/SettingsValues.java index db584fb86..3db4e2449 100644 --- a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/SettingsValues.java +++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/SettingsValues.java @@ -73,6 +73,7 @@ public class SettingsValues { public final boolean mShowsHints; public final boolean mShowsLanguageSwitchKey; public final boolean mShowsEmojiKey; + public final boolean mShowsClipboardKey; public final boolean mUsePersonalizedDicts; public final boolean mUseDoubleSpacePeriod; public final boolean mBlockPotentiallyOffensive; @@ -149,6 +150,7 @@ public class SettingsValues { mShowsHints = prefs.getBoolean(Settings.PREF_SHOW_HINTS, true); mShowsLanguageSwitchKey = prefs.getBoolean(Settings.PREF_SHOW_LANGUAGE_SWITCH_KEY, false); mShowsEmojiKey = prefs.getBoolean(Settings.PREF_SHOW_EMOJI_KEY, false); + mShowsClipboardKey = prefs.getBoolean(Settings.PREF_SHOW_CLIPBOARD_KEY, false); mUsePersonalizedDicts = prefs.getBoolean(Settings.PREF_KEY_USE_PERSONALIZED_DICTS, true); mUseDoubleSpacePeriod = prefs.getBoolean(Settings.PREF_KEY_USE_DOUBLE_SPACE_PERIOD, true) && inputAttributes.mIsGeneralTextInput; @@ -188,7 +190,8 @@ public class SettingsValues { //&& !mInputAttributes.mInputTypeNoAutoCorrect; mSuggestionsEnabledPerUserSettings = !mInputAttributes.mIsPasswordField && readSuggestionsEnabled(prefs); - mIncognitoModeEnabled = Settings.readAlwaysIncognitoMode(prefs) || mInputAttributes.mNoLearning; + mIncognitoModeEnabled = Settings.readAlwaysIncognitoMode(prefs) || mInputAttributes.mNoLearning + || mInputAttributes.mIsPasswordField; mIsInternal = Settings.isInternal(prefs); mHasCustomKeyPreviewAnimationParams = prefs.getBoolean( DebugSettings.PREF_HAS_CUSTOM_KEY_PREVIEW_ANIMATION_PARAMS, false); diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/suggestions/SuggestionStripView.java b/app/src/main/java/org/dslul/openboard/inputmethod/latin/suggestions/SuggestionStripView.java index 2f2400de8..e2c1a2e0c 100644 --- a/app/src/main/java/org/dslul/openboard/inputmethod/latin/suggestions/SuggestionStripView.java +++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/suggestions/SuggestionStripView.java @@ -16,6 +16,8 @@ package org.dslul.openboard.inputmethod.latin.suggestions; +import android.content.ClipData; +import android.content.ClipboardManager; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; @@ -59,6 +61,8 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick public interface Listener { void pickSuggestionManually(SuggestedWordInfo word); void onCodeInput(int primaryCode, int x, int y, boolean isKeyRepeat); + void onTextInput(final String rawText); + CharSequence getSelection(); } static final boolean DBG = DebugFlags.DEBUG_ENABLED; @@ -66,6 +70,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick private final ViewGroup mSuggestionsStrip; private final ImageButton mVoiceKey; + private final ImageButton mClipboardKey; private final ImageButton mOtherKey; MainKeyboardView mMainKeyboardView; @@ -126,6 +131,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick mSuggestionsStrip = findViewById(R.id.suggestions_strip); mVoiceKey = findViewById(R.id.suggestions_strip_voice_key); + mClipboardKey = findViewById(R.id.suggestions_strip_clipboard_key); mOtherKey = findViewById(R.id.suggestions_strip_other_key); mStripVisibilityGroup = new StripVisibilityGroup(this, mSuggestionsStrip); @@ -161,9 +167,13 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick R.styleable.Keyboard, defStyle, R.style.SuggestionStripView); final Drawable iconVoice = keyboardAttr.getDrawable(R.styleable.Keyboard_iconShortcutKey); final Drawable iconIncognito = keyboardAttr.getDrawable(R.styleable.Keyboard_iconIncognitoKey); + final Drawable iconClipboard = keyboardAttr.getDrawable(R.styleable.Keyboard_iconClipboardKey); keyboardAttr.recycle(); mVoiceKey.setImageDrawable(iconVoice); mVoiceKey.setOnClickListener(this); + mClipboardKey.setImageDrawable(iconClipboard); + mClipboardKey.setOnClickListener(this); + mClipboardKey.setOnLongClickListener(this); mOtherKey.setImageDrawable(iconIncognito); } @@ -181,7 +191,8 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick final int visibility = shouldBeVisible ? VISIBLE : (isFullscreenMode ? GONE : INVISIBLE); setVisibility(visibility); final SettingsValues currentSettingsValues = Settings.getInstance().getCurrent(); - mVoiceKey.setVisibility(currentSettingsValues.mShowsVoiceInputKey ? VISIBLE : INVISIBLE); + mVoiceKey.setVisibility(currentSettingsValues.mShowsVoiceInputKey ? VISIBLE : GONE); + mClipboardKey.setVisibility(currentSettingsValues.mShowsClipboardKey ? VISIBLE : (mVoiceKey.getVisibility() == GONE ? INVISIBLE : GONE)); mOtherKey.setVisibility(currentSettingsValues.mIncognitoModeEnabled ? VISIBLE : INVISIBLE); } @@ -256,6 +267,23 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick @Override public boolean onLongClick(final View view) { + if (view == mClipboardKey) { + ClipboardManager clipboardManager = (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE); + ClipData clipData = clipboardManager.getPrimaryClip(); + 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)); + } + } + AudioAndHapticFeedbackManager.getInstance().performHapticAndAudioFeedback( + Constants.NOT_A_CODE, this); + return true; + } AudioAndHapticFeedbackManager.getInstance().performHapticAndAudioFeedback( Constants.NOT_A_CODE, this); return showMoreSuggestions(); @@ -413,6 +441,15 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick false /* isKeyRepeat */); return; } + if (view == mClipboardKey) { + CharSequence selectionSequence = mListener.getSelection(); + if (selectionSequence != null && selectionSequence.length() > 0 + && !Settings.getInstance().getCurrent().mInputAttributes.mIsPasswordField) { + ClipboardManager clipboardManager = (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE); + clipboardManager.setPrimaryClip(ClipData.newPlainText(selectionSequence, selectionSequence)); + } + return; + } final Object tag = view.getTag(); // {@link Integer} tag is set at diff --git a/app/src/main/res/drawable/sym_keyboard_clipboard_dark.xml b/app/src/main/res/drawable/sym_keyboard_clipboard_dark.xml new file mode 100644 index 000000000..c5bd90c58 --- /dev/null +++ b/app/src/main/res/drawable/sym_keyboard_clipboard_dark.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/sym_keyboard_clipboard_light.xml b/app/src/main/res/drawable/sym_keyboard_clipboard_light.xml new file mode 100644 index 000000000..29fa0da12 --- /dev/null +++ b/app/src/main/res/drawable/sym_keyboard_clipboard_light.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/suggestions_strip.xml b/app/src/main/res/layout/suggestions_strip.xml index c6a412e39..7f98671b5 100644 --- a/app/src/main/res/layout/suggestions_strip.xml +++ b/app/src/main/res/layout/suggestions_strip.xml @@ -20,34 +20,45 @@ - - - - + android:soundEffectsEnabled="false"> + + + + + + + diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index 2c6db9f17..7defaf7dc 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -270,6 +270,7 @@ + diff --git a/app/src/main/res/values/keyboard-icons-holo.xml b/app/src/main/res/values/keyboard-icons-holo.xml index 5ef52f264..6cec98fc8 100644 --- a/app/src/main/res/values/keyboard-icons-holo.xml +++ b/app/src/main/res/values/keyboard-icons-holo.xml @@ -29,6 +29,7 @@ @drawable/sym_keyboard_search_holo_dark @drawable/sym_keyboard_tab_holo_dark @drawable/sym_keyboard_voice_holo_dark + @drawable/sym_keyboard_clipboard_dark @drawable/sym_keyboard_incognito_dark @drawable/sym_keyboard_space_holo_dark @drawable/sym_keyboard_shift_locked_holo_dark diff --git a/app/src/main/res/values/keyboard-icons-lxx-dark-parent.xml b/app/src/main/res/values/keyboard-icons-lxx-dark-parent.xml index 04f92b99f..2bc53e0eb 100644 --- a/app/src/main/res/values/keyboard-icons-lxx-dark-parent.xml +++ b/app/src/main/res/values/keyboard-icons-lxx-dark-parent.xml @@ -36,6 +36,7 @@ @drawable/sym_keyboard_previous_lxx_dark @drawable/sym_keyboard_voice_lxx_dark @drawable/sym_keyboard_voice_off_lxx_dark + @drawable/sym_keyboard_clipboard_dark @drawable/sym_keyboard_incognito_lxx_dark @drawable/sym_keyboard_space_lxx_dark @drawable/sym_keyboard_language_switch_lxx_dark diff --git a/app/src/main/res/values/keyboard-icons-lxx-light-parent.xml b/app/src/main/res/values/keyboard-icons-lxx-light-parent.xml index 051095ad6..a566d513e 100644 --- a/app/src/main/res/values/keyboard-icons-lxx-light-parent.xml +++ b/app/src/main/res/values/keyboard-icons-lxx-light-parent.xml @@ -36,6 +36,7 @@ @drawable/sym_keyboard_previous_lxx_light @drawable/sym_keyboard_voice_lxx_light @drawable/sym_keyboard_voice_off_lxx_light + @drawable/sym_keyboard_clipboard_light @drawable/sym_keyboard_incognito_lxx_light @drawable/sym_keyboard_space_lxx_light @drawable/sym_keyboard_language_switch_lxx_light diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d2d0881b4..22285205f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -179,6 +179,10 @@ No voice input methods enabled. Check Languages & input settings. + + Clipboard key + Press to copy, long-press to paste. + Configure input methods diff --git a/app/src/main/res/xml/prefs_screen_preferences.xml b/app/src/main/res/xml/prefs_screen_preferences.xml index aefdcd215..1a3a869bf 100644 --- a/app/src/main/res/xml/prefs_screen_preferences.xml +++ b/app/src/main/res/xml/prefs_screen_preferences.xml @@ -71,4 +71,10 @@ android:title="@string/voice_input" android:defaultValue="true" android:persistent="true" /> +