Clipboard managment pretty much finished

This commit is contained in:
2024-11-03 18:44:31 +01:00
parent ff9d115306
commit 5f1ee64952
18 changed files with 435 additions and 108 deletions
@@ -25,15 +25,16 @@ import android.content.ClipboardManager;
import android.content.Context;
import android.os.Build;
import java.util.ArrayDeque;
import java.util.ArrayList;
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class ClipboardHandler implements ClipboardManager.OnPrimaryClipChangedListener {
public class ClipManager extends ArrayList<ClipData.Item>
implements ClipboardManager.OnPrimaryClipChangedListener {
private final InputMethod mInputMethod;
private final ClipboardManager mClipboardManager;
private ArrayDeque<ClipData> mClips = new ArrayDeque<>();
private long mLastCallbackTimestamp;
public ClipboardHandler(Context context) {
public ClipManager(Context context) {
mInputMethod = (InputMethod) context;
mClipboardManager = (ClipboardManager) mInputMethod.getSystemService(Context.CLIPBOARD_SERVICE);
mClipboardManager.addPrimaryClipChangedListener(this);
@@ -41,20 +42,31 @@ public class ClipboardHandler implements ClipboardManager.OnPrimaryClipChangedLi
@Override
public void onPrimaryClipChanged() {
// The callback can be launched several times, so we have to check if it isn't the same
// clipboard data.
if (mClips.peekFirst() != null) {
if (mClips.peekFirst().equals(mClipboardManager.getPrimaryClip())) {
return;
// The callback can be launched several times at once, so we have to check if it isn't the
// same clipboard data.
if (System.currentTimeMillis() - mLastCallbackTimestamp < 100) {
return;
}
mLastCallbackTimestamp = System.currentTimeMillis();
ClipData clip = mClipboardManager.getPrimaryClip();
if (clip == null) {
return;
}
for (int i = 0; i < clip.getItemCount(); ++i) {
ClipData.Item item = clip.getItemAt(i);
// We do not support non-text clips for now, so all we add are text clips.
if (item.getText() != null) {
add(0, item);
}
if (size() > mInputMethod.mPreferenceHolder.getMaxClipboardItems()) {
remove(size() - 1);
}
}
mClips.addFirst(mClipboardManager.getPrimaryClip());
if (mClips.size() > mInputMethod.mPreferenceHolder.getMaxClipboardItems()) {
mClips.removeLast();
}
mInputMethod.mInputView.setClips(mClips.toArray());
mInputMethod.mInputView.setClips(this);
}
}
@@ -45,12 +45,12 @@ public class InputMethod extends InputMethodService {
public MetaKeyManager mMetaKeyManager;
public KeymapManager mKeymapManager;
public PreferenceHolder mPreferenceHolder;
private ClipboardHandler mClipboardHandler;
public ClipManager mClipManager;
public InputView mInputView;
private int mCurrentCursorPosition;
private Handler mHandler;
private Cycler mSymbolCycler;
private Vibrator mVibrator;
public Vibrator mVibrator;
@Override
public void onCreate() {
@@ -59,7 +59,7 @@ public class InputMethod extends InputMethodService {
mVibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
mMetaKeyManager = new MetaKeyManager(mVibrator);
mKeymapManager = new KeymapManager(this);
mClipboardHandler = new ClipboardHandler(this);
mClipManager = new ClipManager(this);
mHandler = new Handler(Looper.getMainLooper());
mSymbolCycler = new SymbolCycler();
mKeymapManager.cycleKeymaps(mPreferenceHolder.getSelectedKeymaps());
@@ -166,6 +166,7 @@ public class InputMethod extends InputMethodService {
@Override
public void onFinishInput() {
mMetaKeyManager.resetMetaKeyState();
mInputView.mClipboardPopup.dismiss();
}
// Cyclers
@@ -29,23 +29,30 @@ import android.os.Build;
import android.util.AttributeSet;
import android.widget.Button;
import android.widget.HorizontalScrollView;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import java.util.ArrayDeque;
import java.util.ArrayList;
// TODO: programmatically scroll if current selected symbol is outside the visible space of the
// scrollview
public class InputView extends RelativeLayout {
protected final int[] BUTTON_STATE_TOGGLED = { R.attr.state_toggled };
private final InputMethod mInputMethod;
private final LinearLayout.LayoutParams mSymbolLayout;
private final LinearLayout.LayoutParams mCandidateLayout;
private final LinearLayout.LayoutParams mClipLayout;
private LinearLayout mSymbolList;
private LinearLayout mClipsList;
private LinearLayout mClipList;
private Button mStateButton;
private ImageButton mClipboardButton;
private ScrollView mClipboardView;
public PopupWindow mClipboardPopup;
public InputView(Context context, AttributeSet attrs) {
super(context, attrs, 0);
@@ -53,18 +60,17 @@ public class InputView extends RelativeLayout {
mSymbolLayout = new LinearLayout.LayoutParams(
getResources().getDimensionPixelSize(R.dimen.symbol_width),
LinearLayout.LayoutParams.MATCH_PARENT, 0);
mCandidateLayout = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.MATCH_PARENT, 0);
mClipLayout = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT, 0);
mSymbolLayout.setMargins(0, 0,
getResources().getDimensionPixelSize(R.dimen.default_space), 0);
mCandidateLayout.setMargins(0, 0,
getResources().getDimensionPixelSize(R.dimen.default_space), 0);
mClipLayout.setMargins(0,
getResources().getDimensionPixelSize(R.dimen.default_space), 0, 0);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
mSymbolLayout.setMarginEnd(getResources().getDimensionPixelSize(R.dimen.default_space));
mCandidateLayout.setMarginEnd(getResources().getDimensionPixelSize(R.dimen.default_space));
}
}
@@ -72,8 +78,14 @@ public class InputView extends RelativeLayout {
protected void onFinishInflate() {
super.onFinishInflate();
mSymbolList = findViewById(R.id.symbol_list);
mClipsList = findViewById(R.id.clip_list);
mStateButton = findViewById(R.id.state_button);
mClipboardButton = findViewById(R.id.clipboard_button);
mClipboardView = (ScrollView) inflate(this.getContext(), R.layout.clipboard, null);
mClipList = mClipboardView.findViewById(R.id.clip_list);
mClipboardPopup = new PopupWindow(mClipboardView,
getResources().getDimensionPixelSize(R.dimen.clipboard_popup_width),
getResources().getDimensionPixelSize(R.dimen.clipboard_popup_height), true);
mClipboardPopup.setOnDismissListener(() -> mClipboardButton.setImageState(null, true));
mStateButton.setOnClickListener(button -> {
MetaKeyManager metaManager = mInputMethod.mMetaKeyManager;
@@ -89,6 +101,24 @@ public class InputView extends RelativeLayout {
Intent intent = new Intent(getContext(), PreferenceActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getContext().startActivity(intent);
// For some reason, this vibrates by default, so we don't need to call the vibrator.
return true;
});
mClipboardButton.setOnClickListener(button -> {
mClipboardPopup.showAsDropDown(mClipboardButton,
-(mClipboardPopup.getWidth() - mClipboardButton.getWidth()) / 2, 0);
mClipboardButton.setImageState(BUTTON_STATE_TOGGLED, true);
});
mClipboardButton.setOnLongClickListener(button -> {
// On a long click, we just send the latest clip (if any).
if (!mInputMethod.mClipManager.isEmpty()
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
mInputMethod.getCurrentInputConnection()
.commitText(mInputMethod.mClipManager.get(0).getText(), 1);
}
return true;
});
}
@@ -135,26 +165,33 @@ public class InputView extends RelativeLayout {
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void setClips(Object[] clips) {
for (int i = 0; i < clips.length; ++i) {
Button b = (Button) mClipsList.getChildAt(i);
ClipData clip = (ClipData) clips[i];
public void setClips(ArrayList<ClipData.Item> items) {
for (int i = 0; i < items.size(); ++i) {
ClipData.Item item = items.get(i);
LinearLayout clipView = (LinearLayout) mClipList.getChildAt(i);
if (b == null) {
b = (Button) inflate(this.getContext(), R.layout.candidate, null);
b.setTag(i);
b.setLayoutParams(mCandidateLayout);
mClipsList.addView(b);
if (clipView == null) {
clipView = (LinearLayout) inflate(this.getContext(), R.layout.clip, null);
clipView.setTag(i);
clipView.setLayoutParams(mClipLayout);
mClipList.addView(clipView);
}
ClipData.Item item = clip.getItemAt(0);
b.setText(item.coerceToText(this.getContext()).toString());
Button pasteButton = clipView.findViewById(R.id.paste_button);
pasteButton.setText(item.getText());
pasteButton.setOnClickListener(button -> mInputMethod.getCurrentInputConnection().commitText(item.getText(), 1));
LinearLayout finalClipView = clipView;
clipView.findViewById(R.id.button_delete).setOnClickListener(button -> {
mClipList.removeView(finalClipView);
mInputMethod.mClipManager.remove(item);
});
}
}
public void setSymbolsVisible(boolean state) {
findViewById(R.id.symbol_list_container).setVisibility(state ? VISIBLE : GONE);
findViewById(R.id.clip_list_container).setVisibility(state ? GONE : VISIBLE);
mSymbolList.setVisibility(state ? VISIBLE : GONE);
}
public void setSymbols(ArrayList<String> strings) {
+13 -5
View File
@@ -17,17 +17,25 @@
~
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<selector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item app:state_toggled="true">
<shape android:shape="rectangle">
<solid android:color="@color/button_toggled" />
<corners android:bottomLeftRadius="@dimen/default_border_radius"
android:bottomRightRadius="@dimen/default_border_radius" />
</shape>
</item>
<item android:state_pressed="false">
<shape android:shape="rectangle">
<solid android:color="#444" />
<corners android:radius="8dp" />
<solid android:color="@color/button" />
<corners android:radius="@dimen/default_border_radius" />
</shape>
</item>
<item android:state_pressed="true">
<shape android:shape="rectangle">
<solid android:color="#666" />
<corners android:radius="8dp" />
<solid android:color="@color/button_active" />
<corners android:radius="@dimen/default_border_radius" />
</shape>
</item>
</selector>
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ An input method for the Unihertz Titan/physical keyboard phones
~ Copyright (C) 2024 Emil Kosz
~
~ This program is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
~ (at your option) any later version.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with this program. If not, see <https://www.gnu.org/licenses/>.
~
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false">
<shape android:shape="rectangle">
<solid android:color="@android:color/transparent" />
</shape>
</item>
<item android:state_pressed="true">
<shape android:shape="rectangle">
<solid android:color="@color/button_active" />
</shape>
</item>
</selector>
+6 -4
View File
@@ -20,14 +20,16 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<item android:state_pressed="false">
<shape android:shape="rectangle">
<solid android:color="#333" />
<corners android:bottomLeftRadius="0dp" android:bottomRightRadius="0dp" android:radius="8dp" />
<solid android:color="@color/candidate" />
<corners android:topLeftRadius="@dimen/default_border_radius"
android:topRightRadius="@dimen/default_border_radius"/>
</shape>
</item>
<item android:state_pressed="true">
<shape android:shape="rectangle">
<solid android:color="#555" />
<corners android:bottomLeftRadius="0dp" android:bottomRightRadius="0dp" android:radius="8dp" />
<solid android:color="@color/candidate_active" />
<corners android:topLeftRadius="@dimen/default_border_radius"
android:topRightRadius="@dimen/default_border_radius" />
</shape>
</item>
</selector>
+71
View File
@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ An input method for the Unihertz Titan/physical keyboard phones
~ Copyright (C) 2024 Emil Kosz
~
~ This program is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
~ (at your option) any later version.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with this program. If not, see <https://www.gnu.org/licenses/>.
~
-->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Main board -->
<item>
<inset android:insetTop="7.5%">
<shape android:shape="rectangle">
<stroke android:color="@color/text_color" android:width="2dp" />
<corners android:radius="2dp" />
</shape>
</inset>
</item>
<!-- The clip -->
<item>
<inset android:insetLeft="30%"
android:insetRight="30%"
android:insetBottom="80%">
<shape android:shape="rectangle">
<solid android:color="@color/text_color"/>
<corners android:radius="2dp" />
</shape>
</inset>
</item>
<!-- Squiggles -->
<item>
<inset android:insetBottom="25%"
android:insetLeft="20%"
android:insetRight="20%">
<shape android:shape="line">
<stroke android:width="2dp" android:color="@color/text_color" />
</shape>
</inset>
</item>
<item>
<inset
android:insetTop="10%"
android:insetLeft="20%"
android:insetRight="20%">
<shape android:shape="line">
<stroke android:width="2dp" android:color="@color/text_color" />
</shape>
</inset>
</item>
<item>
<inset
android:insetTop="45%"
android:insetLeft="20%"
android:insetRight="40%">
<shape android:shape="line">
<stroke android:width="2dp" android:color="@color/text_color" />
</shape>
</inset>
</item>
</layer-list>
@@ -17,13 +17,8 @@
~
-->
<Button xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/InputViewCandidate"
android:drawablePadding="@dimen/candidate_side_padding"
android:ellipsize="end"
android:maxWidth="@dimen/candidate_max_width"
android:paddingLeft="@dimen/candidate_side_padding"
android:paddingRight="@dimen/candidate_side_padding"
android:singleLine="true">
</Button>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/button_toggled" />
<corners android:radius="@dimen/default_border_radius" />
</shape>
+61
View File
@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ An input method for the Unihertz Titan/physical keyboard phones
~ Copyright (C) 2024 Emil Kosz
~
~ This program is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
~ (at your option) any later version.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with this program. If not, see <https://www.gnu.org/licenses/>.
~
-->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<inset android:insetTop="15%"
android:insetLeft="10%"
android:insetRight="10%">
<shape android:shape="rectangle">
<stroke android:width="2dp"
android:color="@color/danger_text_color" />
<corners android:bottomLeftRadius="4dp"
android:bottomRightRadius="4dp"/>
</shape>
</inset>
</item>
<item>
<inset android:insetBottom="65%">
<shape android:shape="line">
<stroke android:width="2dp" android:color="@color/danger_text_color" />
</shape>
</inset>
</item>
<item>
<inset android:insetRight="30%"
android:insetLeft="30%"
android:insetBottom="75%">
<shape android:shape="rectangle">
<stroke android:width="2dp"
android:color="@color/danger_text_color" />
<corners android:radius="8dp" />
</shape>
</inset>
</item>
<!-- Stripes -->
<item>
<inset android:insetTop="15%"
android:insetLeft="35%"
android:insetRight="35%">
<shape android:shape="rectangle">
<stroke android:width="2dp" android:color="@color/danger_text_color" />
</shape>
</inset>
</item>
</layer-list>
+52
View File
@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ An input method for the Unihertz Titan/physical keyboard phones
~ Copyright (C) 2024 Emil Kosz
~
~ This program is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
~ (at your option) any later version.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with this program. If not, see <https://www.gnu.org/licenses/>.
~
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="?android:listDivider">
<Button
android:id="@+id/paste_button"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/button_transparent"
android:ellipsize="marquee"
android:gravity="center_vertical"
android:padding="@dimen/default_space"
android:singleLine="true"
android:text="@string/clip_default_text"
android:textColor="@color/text_color"
android:textSize="@dimen/default_text_size" />
<ImageButton
android:id="@+id/button_delete"
android:layout_width="@dimen/button_size"
android:layout_height="@dimen/button_size"
android:background="@drawable/button_transparent"
android:contentDescription="@string/delete_button_description"
android:paddingLeft="@dimen/image_button_horizontal_padding"
android:paddingTop="@dimen/image_button_vertical_padding"
android:paddingRight="@dimen/image_button_horizontal_padding"
android:paddingBottom="@dimen/image_button_vertical_padding"
android:src="@drawable/trashcan"
tools:ignore="UnusedAttribute" />
</LinearLayout>
+31
View File
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ An input method for the Unihertz Titan/physical keyboard phones
~ Copyright (C) 2024 Emil Kosz
~
~ This program is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
~ (at your option) any later version.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with this program. If not, see <https://www.gnu.org/licenses/>.
~
-->
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/popup"
android:padding="@dimen/default_space">
<LinearLayout
android:id="@+id/clip_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
</ScrollView>
+23 -23
View File
@@ -18,10 +18,11 @@
-->
<cfpi_fpsi.eu.titanboard.InputView xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/InputViewBackground"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="@color/background"
android:paddingLeft="@dimen/default_space"
android:paddingTop="@dimen/default_space"
android:paddingRight="@dimen/default_space">
@@ -30,13 +31,12 @@
android:id="@+id/symbol_list_container"
android:layout_width="match_parent"
android:layout_height="@dimen/container_height"
android:layout_alignTop="@id/state_button"
android:layout_alignTop="@id/clipboard_button"
android:layout_marginEnd="@dimen/default_space"
android:layout_marginRight="@dimen/default_space"
android:layout_marginBottom="0dp"
android:layout_toStartOf="@+id/state_button"
android:layout_toLeftOf="@id/state_button"
android:visibility="gone">
android:layout_toStartOf="@+id/clipboard_button"
android:layout_toLeftOf="@id/clipboard_button">
<LinearLayout
android:id="@+id/symbol_list"
@@ -47,32 +47,32 @@
</LinearLayout>
</HorizontalScrollView>
<HorizontalScrollView
android:id="@+id/clip_list_container"
android:layout_width="match_parent"
android:layout_height="@dimen/container_height"
android:layout_alignTop="@id/state_button"
<ImageButton
android:id="@+id/clipboard_button"
android:layout_width="@dimen/button_size"
android:layout_height="@dimen/button_size"
android:layout_marginEnd="@dimen/default_space"
android:layout_marginRight="@dimen/default_space"
android:layout_marginBottom="0dp"
android:layout_toStartOf="@+id/state_button"
android:layout_toLeftOf="@id/state_button">
<LinearLayout
android:id="@+id/clip_list"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal" />
</HorizontalScrollView>
android:layout_toStartOf="@id/state_button"
android:layout_toLeftOf="@id/state_button"
android:background="@drawable/button"
android:contentDescription="@string/clipboard_button_description"
android:paddingLeft="@dimen/image_button_horizontal_padding"
android:paddingTop="@dimen/image_button_vertical_padding"
android:paddingRight="@dimen/image_button_horizontal_padding"
android:paddingBottom="@dimen/image_button_vertical_padding"
android:src="@drawable/clipboard"
tools:ignore="UnusedAttribute" />
<Button
android:id="@+id/state_button"
style="@style/InputViewButton"
android:layout_width="@dimen/button_width"
android:layout_height="@dimen/button_height"
android:layout_width="@dimen/button_size"
android:layout_height="@dimen/button_size"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:background="@drawable/button"
android:text="@string/state_button_default"
android:textColor="@color/text_color"
android:textSize="@dimen/default_text_size" />
</cfpi_fpsi.eu.titanboard.InputView>
+4 -1
View File
@@ -18,8 +18,11 @@
-->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/InputViewCandidate"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/candidate"
android:gravity="center"
android:textColor="@color/text_color"
android:textSize="@dimen/default_text_size">
</TextView>
@@ -18,18 +18,5 @@
-->
<resources>
<style name="InputViewBackground">
<item name="android:background">#222</item>
</style>
<style name="InputViewButton">
<item name="android:background">@drawable/button</item>
<item name="android:textColor">#FFF</item>
</style>
<style name="InputViewCandidate">
<item name="android:background">@drawable/candidate</item>
<item name="android:textColor">#FFF</item>
</style>
<attr name="state_toggled" format="boolean" />
</resources>
+29
View File
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ An input method for the Unihertz Titan/physical keyboard phones
~ Copyright (C) 2024 Emil Kosz
~
~ This program is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
~ (at your option) any later version.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with this program. If not, see <https://www.gnu.org/licenses/>.
~
-->
<resources>
<color name="background">#222</color>
<color name="button">#444</color>
<color name="button_toggled">#555</color>
<color name="button_active">#666</color>
<color name="candidate">#333</color>
<color name="candidate_active">#666</color>
<color name="text_color">#EEE</color>
<color name="danger_text_color">#FF0000</color>
</resources>
+7 -5
View File
@@ -20,10 +20,12 @@
<resources>
<dimen name="default_space">8dp</dimen>
<dimen name="container_height">56dp</dimen>
<dimen name="button_width">48dp</dimen>
<dimen name="button_height">48dp</dimen>
<dimen name="candidate_max_width">196dp</dimen>
<dimen name="candidate_side_padding">12dp</dimen>
<dimen name="button_size">48dp</dimen>
<dimen name="symbol_width">40dp</dimen>
<dimen name="default_text_size">18sp</dimen>
<dimen name="default_text_size">16sp</dimen>
<dimen name="image_button_vertical_padding">12dp</dimen>
<dimen name="image_button_horizontal_padding">14dp</dimen>
<dimen name="clipboard_popup_width">196dp</dimen>
<dimen name="clipboard_popup_height">256dp</dimen>
<dimen name="default_border_radius">8dp</dimen>
</resources>
+8 -4
View File
@@ -2,10 +2,18 @@
<string name="app_name">Titanboard</string>
<string name="preferences_name">Titanboard preferences</string>
<string name="keymap_default">en</string>
<string name="cycle_speed_default">500</string>
<string name="clipboard_max_items_default">10</string>
<string name="state_button_default">\??</string>
<string name="state_button_alt_locked">#!</string>
<string name="state_button_alt_latched">#?</string>
<string name="delete_button_description">Delete clipboard item</string>
<string name="clipboard_button_description">Open clipboard or paste first item on long press</string>
<string name="clip_default_text">Clip</string>
<string name="preferences_label_floating_interface">Floating interface</string>
<string name="preferences_label_cycle_speed">Cycling speed</string>
<string name="preferences_label_clipboard_max_items">Maximum clipboard items</string>
@@ -24,8 +32,4 @@
<string name="preferences_key_keymaps">selected_keymaps</string>
<string name="preferences_key_cycle_speed">cycle_speed</string>
<string name="preferences_key_clipboard_max_items">clipboard_items</string>
<string name="keymap_default">en</string>
<string name="cycle_speed_default">500</string>
<string name="clipboard_max_items_default">10</string>
</resources>
+1
View File
@@ -21,6 +21,7 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<SwitchPreference
android:defaultValue="@bool/floating_ui_default"
android:enabled="false"
android:key="@string/preferences_key_floating_interface"
android:summary="@string/preferences_summary_floating_interface"
android:title="@string/preferences_label_floating_interface" />