abouttreesummaryrefslogcommitdiff
path: root/srcs/juloo.keyboard2
diff options
context:
space:
mode:
authorJules Aguillon2025-07-27 22:09:45 +0200
committerJules Aguillon2025-12-28 17:56:37 +0100
commit98c1b8db82c0da8f49eb12d18c9001a57009eca5 (patch)
treefaddcbd29f19cb5c526f0a37c078ec11fc901c85 /srcs/juloo.keyboard2
parentdfaf4dbb5766bf134cbf97d0516493e2256d2e5a (diff)
downloadunexpected-keyboard-98c1b8db82c0da8f49eb12d18c9001a57009eca5.tar.gz
unexpected-keyboard-98c1b8db82c0da8f49eb12d18c9001a57009eca5.zip
Candidates view
The `CandidatesView` is implemented as a `LinearLayout` that is divided horizontally with up to 3 `TextView`. It might in the future contain buttons on the sides. The candidate view is nested into the input view rather than using Android's `setCandidatesView` and callbacks as the API is unreliable and complicated. The first suggestion goes in the middle to be more accessible. The second suggestion goes on the right to be more accessible to the right-handed, because it must go somewhere.
Diffstat (limited to 'srcs/juloo.keyboard2')
-rw-r--r--srcs/juloo.keyboard2/CandidatesView.java104
-rw-r--r--srcs/juloo.keyboard2/Config.java3
-rw-r--r--srcs/juloo.keyboard2/KeyEventHandler.java6
-rw-r--r--srcs/juloo.keyboard2/Keyboard2.java30
-rw-r--r--srcs/juloo.keyboard2/Keyboard2View.java2
-rw-r--r--srcs/juloo.keyboard2/Logs.java2
6 files changed, 139 insertions, 8 deletions
diff --git a/srcs/juloo.keyboard2/CandidatesView.java b/srcs/juloo.keyboard2/CandidatesView.java
new file mode 100644
index 0000000..232ed23
--- /dev/null
+++ b/srcs/juloo.keyboard2/CandidatesView.java
@@ -0,0 +1,104 @@
+package juloo.keyboard2;
+
+import android.content.Context;
+import android.text.InputType;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.inputmethod.EditorInfo;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import java.util.ArrayList;
+import java.util.List;
+
+public class CandidatesView extends LinearLayout
+{
+ static final int NUM_CANDIDATES = 3;
+
+ Config _config;
+
+ /** Candidates currently visible. Entries can be [null] when there are less
+ than [NUM_CANDIDATES] suggestions. */
+ String[] _items = new String[NUM_CANDIDATES];
+
+ /** Text views showing the candidates in [_items]. Text views visibility is
+ set to [GONE] when there are less than [NUM_CANDIDATES] suggestions. */
+ TextView[] _item_views = new TextView[NUM_CANDIDATES];
+
+ public CandidatesView(Context context, AttributeSet attrs)
+ {
+ super(context, attrs);
+ _config = Config.globalConfig();
+ }
+
+ @Override
+ protected void onFinishInflate()
+ {
+ super.onFinishInflate();
+ setup_item_view(0, R.id.candidates_middle);
+ setup_item_view(1, R.id.candidates_right);
+ setup_item_view(2, R.id.candidates_left);
+ }
+
+ public void set_candidates(List<String> suggestions)
+ {
+ int s_count = suggestions.size();
+ for (int i = 0; i < _item_views.length; i++)
+ {
+ TextView v = _item_views[i];
+ if (i < s_count)
+ {
+ String it = suggestions.get(i);
+ _items[i] = it;
+ v.setText(it);
+ v.setVisibility(View.VISIBLE);
+ }
+ else
+ {
+ _items[i] = null;
+ v.setVisibility(View.GONE);
+ }
+ }
+ }
+
+ private void setup_item_view(final int item_index, int item_id)
+ {
+ TextView v = (TextView)findViewById(item_id);
+ v.setOnClickListener(new View.OnClickListener()
+ {
+ @Override
+ public void onClick(View _v)
+ {
+ String it = _items[item_index];
+ if (it != null)
+ _config.handler.suggestion_entered(it);
+ }
+ });
+ v.setVisibility(View.GONE);
+ _item_views[item_index] = v;
+ }
+
+ public static boolean should_show(EditorInfo info)
+ {
+ int variation = info.inputType & InputType.TYPE_MASK_VARIATION;
+ int flags = info.inputType & InputType.TYPE_MASK_FLAGS;
+ switch (info.inputType & InputType.TYPE_MASK_CLASS)
+ {
+ case InputType.TYPE_CLASS_TEXT:
+ switch (variation)
+ {
+ case InputType.TYPE_TEXT_VARIATION_PASSWORD:
+ case InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD:
+ case InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD:
+ return false;
+ default:
+ if ((flags & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS) != 0)
+ return false; // Editor requested that we don't show suggestions
+ return true;
+ }
+ case InputType.TYPE_CLASS_NUMBER:
+ // Beware of TYPE_NUMBER_VARIATION_PASSWORD
+ return false;
+ default: return false;
+ }
+ }
+}
diff --git a/srcs/juloo.keyboard2/Config.java b/srcs/juloo.keyboard2/Config.java
index 64e2d87..775c206 100644
--- a/srcs/juloo.keyboard2/Config.java
+++ b/srcs/juloo.keyboard2/Config.java
@@ -75,6 +75,7 @@ public final class Config
// Dynamically set
/** Configuration options implied by the connected editor. */
public EditorConfig editor_config;
+ public boolean should_show_candidates_view;
public boolean shouldOfferVoiceTyping;
public ExtraKeys extra_keys_subtype;
public Map<KeyValue, KeyboardData.PreferredPos> extra_keys_param;
@@ -101,6 +102,7 @@ public final class Config
// from prefs
refresh(res, foldableUnfolded);
// initialized later
+ should_show_candidates_view = false;
shouldOfferVoiceTyping = false;
extra_keys_subtype = null;
handler = h;
@@ -291,6 +293,7 @@ public final class Config
public void key_down(KeyValue value, boolean is_swipe);
public void key_up(KeyValue value, Pointers.Modifiers mods);
public void mods_changed(Pointers.Modifiers mods);
+ public void suggestion_entered(String text);
}
/** Config migrations. */
diff --git a/srcs/juloo.keyboard2/KeyEventHandler.java b/srcs/juloo.keyboard2/KeyEventHandler.java
index fc3a641..145acbe 100644
--- a/srcs/juloo.keyboard2/KeyEventHandler.java
+++ b/srcs/juloo.keyboard2/KeyEventHandler.java
@@ -111,6 +111,12 @@ public final class KeyEventHandler
}
@Override
+ public void suggestion_entered(String text)
+ {
+ // TODO
+ }
+
+ @Override
public void paste_from_clipboard_pane(String content)
{
send_text(content);
diff --git a/srcs/juloo.keyboard2/Keyboard2.java b/srcs/juloo.keyboard2/Keyboard2.java
index 1efe0f5..c7d7e3d 100644
--- a/srcs/juloo.keyboard2/Keyboard2.java
+++ b/srcs/juloo.keyboard2/Keyboard2.java
@@ -29,7 +29,10 @@ import juloo.keyboard2.prefs.LayoutsPreference;
public class Keyboard2 extends InputMethodService
implements SharedPreferences.OnSharedPreferenceChangeListener
{
+ /** The view containing the keyboard and candidates view. */
+ private ViewGroup _container_view;
private Keyboard2View _keyboardView;
+ private CandidatesView _candidates_view;
private KeyEventHandler _keyeventhandler;
/** If not 'null', the layout to use instead of [_config.current_layout]. */
private KeyboardData _currentSpecialLayout;
@@ -115,9 +118,8 @@ public class Keyboard2 extends InputMethodService
Config.initGlobalConfig(prefs, getResources(), _keyeventhandler, _foldStateTracker.isUnfolded());
prefs.registerOnSharedPreferenceChangeListener(this);
_config = Config.globalConfig();
- _keyboardView = (Keyboard2View)inflate_view(R.layout.keyboard);
- _keyboardView.reset();
Logs.set_debug_logs(getResources().getBoolean(R.bool.debug_logs));
+ create_keyboard_view();
ClipboardHistoryService.on_startup(this, _keyeventhandler);
_foldStateTracker.setChangedCallback(() -> { refresh_config(); });
}
@@ -129,6 +131,13 @@ public class Keyboard2 extends InputMethodService
_foldStateTracker.close();
}
+ private void create_keyboard_view()
+ {
+ _container_view = (ViewGroup)inflate_view(R.layout.keyboard);
+ _keyboardView = (Keyboard2View)_container_view.findViewById(R.id.keyboard_view);
+ _candidates_view = (CandidatesView)_container_view.findViewById(R.id.candidates_view);
+ }
+
private List<InputMethodSubtype> getEnabledSubtypes(InputMethodManager imm)
{
String pkg = getPackageName();
@@ -198,6 +207,13 @@ public class Keyboard2 extends InputMethodService
_localeTextLayout = default_layout;
}
+ private void refresh_candidates_view(EditorInfo info)
+ {
+ boolean should_show = CandidatesView.should_show(info);
+ _config.should_show_candidates_view = should_show;
+ _candidates_view.setVisibility(should_show ? View.VISIBLE : View.GONE);
+ }
+
/** Might re-create the keyboard view. [_keyboardView.setKeyboard()] and
[setInputView()] must be called soon after. */
private void refresh_config()
@@ -208,11 +224,13 @@ public class Keyboard2 extends InputMethodService
// Refreshing the theme config requires re-creating the views
if (prev_theme != _config.theme)
{
- _keyboardView = (Keyboard2View)inflate_view(R.layout.keyboard);
+ create_keyboard_view();
_emojiPane = null;
_clipboard_pane = null;
- setInputView(_keyboardView);
+ setInputView(_container_view);
}
+ // Set keyboard background opacity
+ _container_view.getBackground().setAlpha(_config.keyboardOpacity);
_keyboardView.reset();
}
@@ -234,10 +252,11 @@ public class Keyboard2 extends InputMethodService
{
_config.editor_config.refresh(info, getResources());
refresh_config();
+ refresh_candidates_view(info);
_currentSpecialLayout = refresh_special_layout();
_keyboardView.setKeyboard(current_layout());
_keyeventhandler.started(_config);
- setInputView(_keyboardView);
+ setInputView(_container_view);
Logs.debug_startup_input_view(info, _config);
}
@@ -252,7 +271,6 @@ public class Keyboard2 extends InputMethodService
v.requestApplyInsets();
}
-
@Override
public void updateFullscreenMode() {
super.updateFullscreenMode();
diff --git a/srcs/juloo.keyboard2/Keyboard2View.java b/srcs/juloo.keyboard2/Keyboard2View.java
index 58c689d..068ef67 100644
--- a/srcs/juloo.keyboard2/Keyboard2View.java
+++ b/srcs/juloo.keyboard2/Keyboard2View.java
@@ -344,8 +344,6 @@ public class Keyboard2View extends View
@Override
protected void onDraw(Canvas canvas)
{
- // Set keyboard background opacity
- getBackground().setAlpha(_config.keyboardOpacity);
float y = _tc.margin_top;
for (KeyboardData.Row row : _keyboard.rows)
{
diff --git a/srcs/juloo.keyboard2/Logs.java b/srcs/juloo.keyboard2/Logs.java
index 1bef51c..a956305 100644
--- a/srcs/juloo.keyboard2/Logs.java
+++ b/srcs/juloo.keyboard2/Logs.java
@@ -26,6 +26,8 @@ public final class Logs
_debug_logs.println("swapEnterActionKey: "
+conf.editor_config.swapEnterActionKey);
_debug_logs.println("actionLabel: "+conf.editor_config.actionLabel);
+ _debug_logs.println("should_show_candidates_view: "
+ +conf.should_show_candidates_view);
}
public static void debug_config_migration(int from_version, int to_version)