Skip to content

Commit 32a4c13

Browse files
Julowpashol
authored andcommitted
Refactor: Split DeviceLocales out of Keyboard2 (Julow#1154)
* Refactor: Split DeviceLocales out of Keyboard2 This moves the code from Keyboard2 that handles the active IME subtypes and the current one. The goal is to access this information from the dictionary activity while simplifying the code of Keyboard2. * Refresh the candidates view when subtype changes This fixes the status message being inconsistently shown. * Refactor: Load DeviceLocales less often Previously, [DeviceLocales.load()] was called everytime the keyboard was shown on the screen. This operation is moderately costly and only need to be done when the IME subtype changes. * EditorConfig: Fix crash on Android 9
1 parent 6d73b0c commit 32a4c13

File tree

3 files changed

+107
-61
lines changed

3 files changed

+107
-61
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package juloo.keyboard2;
2+
3+
import android.content.Context;
4+
import android.os.Build.VERSION;
5+
import android.view.inputmethod.InputMethodInfo;
6+
import android.view.inputmethod.InputMethodManager;
7+
import android.view.inputmethod.InputMethodSubtype;
8+
import java.util.ArrayList;
9+
import java.util.List;
10+
11+
public final class DeviceLocales
12+
{
13+
public final List<Loc> installed;
14+
public final Loc default_;
15+
16+
public static DeviceLocales load(Context ctx)
17+
{
18+
InputMethodManager imm =
19+
(InputMethodManager)ctx.getSystemService(Context.INPUT_METHOD_SERVICE);
20+
List<Loc> locs = get_installed_locales(ctx.getPackageName(), imm);
21+
return new DeviceLocales(locs, current_locale(imm, locs));
22+
}
23+
24+
/** Extra keys required by all the installed locales. */
25+
public ExtraKeys extra_keys()
26+
{
27+
List<ExtraKeys> extra_keys = new ArrayList<ExtraKeys>();
28+
for (Loc l : installed)
29+
extra_keys.add(l.extra_keys);
30+
return ExtraKeys.merge(extra_keys);
31+
}
32+
33+
public static final class Loc
34+
{
35+
public final String lang_tag;
36+
public final String script;
37+
public final String default_layout; // Might be [null]
38+
public final ExtraKeys extra_keys;
39+
40+
public Loc(InputMethodSubtype st)
41+
{
42+
lang_tag = st.getLanguageTag();
43+
script = st.getExtraValueOf("script");
44+
default_layout = st.getExtraValueOf("default_layout");
45+
String extra_keys_s = st.getExtraValueOf("extra_keys");
46+
extra_keys = (extra_keys_s != null) ?
47+
ExtraKeys.parse(script, extra_keys_s) : ExtraKeys.EMPTY;
48+
}
49+
}
50+
51+
private DeviceLocales(List<Loc> locs, Loc def)
52+
{ installed = locs; default_ = def; }
53+
54+
private static List<Loc> get_installed_locales(String pkg, InputMethodManager imm)
55+
{
56+
List<Loc> locs = new ArrayList<Loc>();
57+
for (InputMethodInfo imi : imm.getEnabledInputMethodList())
58+
if (imi.getPackageName().equals(pkg))
59+
{
60+
for (InputMethodSubtype subtype :
61+
imm.getEnabledInputMethodSubtypeList(imi, true))
62+
locs.add(new Loc(subtype));
63+
break;
64+
}
65+
return locs;
66+
}
67+
68+
private static Loc current_locale(InputMethodManager imm, List<Loc> installed)
69+
{
70+
// Android might return a random subtype, for example, the first in the
71+
// list alphabetically.
72+
InputMethodSubtype current_subtype = imm.getCurrentInputMethodSubtype();
73+
if (current_subtype == null)
74+
return null;
75+
if (VERSION.SDK_INT < 24)
76+
return new Loc(current_subtype);
77+
String default_lang_tag = current_subtype.getLanguageTag();
78+
for (Loc l : installed)
79+
if (l.lang_tag.equals(default_lang_tag))
80+
return l;
81+
return null;
82+
}
83+
}

srcs/juloo.keyboard2/EditorConfig.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package juloo.keyboard2;
22

33
import android.content.res.Resources;
4+
import android.os.Build.VERSION;
45
import android.text.InputType;
56
import android.text.TextUtils;
67
import android.view.inputmethod.EditorInfo;
8+
import juloo.keyboard2.CandidatesView;
79

810
public final class EditorConfig
911
{
@@ -27,10 +29,14 @@ public final class EditorConfig
2729
public boolean caps_initially_updated = false;
2830

2931
/** CurrentlyTypedWord. */
30-
public CharSequence initial_text_before_cursor = null;
32+
public CharSequence initial_text_before_cursor = null; // Might be [null].
3133
public int initial_sel_start;
3234
public int initial_sel_end;
3335

36+
/** Suggestions. */
37+
// Doesn't override [_config.suggestions_enabled].
38+
public boolean should_show_candidates_view;
39+
3440
public EditorConfig() {}
3541

3642
public void refresh(EditorInfo info, Resources res)
@@ -72,9 +78,12 @@ public void refresh(EditorInfo info, Resources res)
7278
caps_initially_enabled = (info.initialCapsMode != 0);
7379
caps_initially_updated = caps_should_update_state(info);
7480
/* CurrentlyTypedWord */
75-
initial_text_before_cursor = info.getInitialTextBeforeCursor(10, 0);
81+
if (VERSION.SDK_INT >= 30)
82+
initial_text_before_cursor = info.getInitialTextBeforeCursor(10, 0);
7683
initial_sel_start = info.initialSelStart;
7784
initial_sel_end = info.initialSelEnd;
85+
/* Suggestions */
86+
should_show_candidates_view = CandidatesView.should_show(info);
7887
}
7988

8089
String actionLabel_of_imeAction(int action, Resources res)

srcs/juloo.keyboard2/Keyboard2.java

Lines changed: 13 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
import android.view.*;
1414
import android.view.inputmethod.EditorInfo;
1515
import android.view.inputmethod.InputConnection;
16-
import android.view.inputmethod.InputMethodInfo;
1716
import android.view.inputmethod.InputMethodManager;
1817
import android.view.inputmethod.InputMethodSubtype;
1918
import android.widget.FrameLayout;
@@ -38,6 +37,8 @@ public class Keyboard2 extends InputMethodService
3837
private KeyboardData _currentSpecialLayout;
3938
/** Layout associated with the currently selected locale. Not 'null'. */
4039
private KeyboardData _localeTextLayout;
40+
/** Installed and current locales. */
41+
private DeviceLocales _device_locales;
4142
private ViewGroup _emojiPane = null;
4243
private ViewGroup _clipboard_pane = null;
4344
private Handler _handler;
@@ -119,6 +120,7 @@ public void onCreate()
119120
prefs.registerOnSharedPreferenceChangeListener(this);
120121
_config = Config.globalConfig();
121122
Logs.set_debug_logs(getResources().getBoolean(R.bool.debug_logs));
123+
refreshSubtypeImm();
122124
create_keyboard_view();
123125
ClipboardHistoryService.on_startup(this, _keyeventhandler);
124126
_foldStateTracker.setChangedCallback(() -> { refresh_config(); });
@@ -138,79 +140,31 @@ private void create_keyboard_view()
138140
_candidates_view = (CandidatesView)_container_view.findViewById(R.id.candidates_view);
139141
}
140142

141-
private List<InputMethodSubtype> getEnabledSubtypes(InputMethodManager imm)
142-
{
143-
String pkg = getPackageName();
144-
for (InputMethodInfo imi : imm.getEnabledInputMethodList())
145-
if (imi.getPackageName().equals(pkg))
146-
return imm.getEnabledInputMethodSubtypeList(imi, true);
147-
return Arrays.asList();
148-
}
149-
150-
private ExtraKeys extra_keys_of_subtype(InputMethodSubtype subtype)
151-
{
152-
String extra_keys = subtype.getExtraValueOf("extra_keys");
153-
String script = subtype.getExtraValueOf("script");
154-
if (extra_keys != null)
155-
return ExtraKeys.parse(script, extra_keys);
156-
return ExtraKeys.EMPTY;
157-
}
158-
159-
private void refreshAccentsOption(InputMethodManager imm, List<InputMethodSubtype> enabled_subtypes)
160-
{
161-
List<ExtraKeys> extra_keys = new ArrayList<ExtraKeys>();
162-
for (InputMethodSubtype s : enabled_subtypes)
163-
extra_keys.add(extra_keys_of_subtype(s));
164-
_config.extra_keys_subtype = ExtraKeys.merge(extra_keys);
165-
}
166-
167143
InputMethodManager get_imm()
168144
{
169145
return (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
170146
}
171147

172-
private InputMethodSubtype defaultSubtypes(InputMethodManager imm, List<InputMethodSubtype> enabled_subtypes)
173-
{
174-
if (VERSION.SDK_INT < 24)
175-
return imm.getCurrentInputMethodSubtype();
176-
// Android might return a random subtype, for example, the first in the
177-
// list alphabetically.
178-
InputMethodSubtype current_subtype = imm.getCurrentInputMethodSubtype();
179-
if (current_subtype == null)
180-
return null;
181-
for (InputMethodSubtype s : enabled_subtypes)
182-
if (s.getLanguageTag().equals(current_subtype.getLanguageTag()))
183-
return s;
184-
return null;
185-
}
186-
187148
private void refreshSubtypeImm()
188149
{
189-
InputMethodManager imm = get_imm();
190150
_config.shouldOfferVoiceTyping = true;
191151
KeyboardData default_layout = null;
192-
_config.extra_keys_subtype = null;
193-
if (VERSION.SDK_INT >= 12)
152+
_device_locales = DeviceLocales.load(this);
153+
if (_device_locales.default_ != null)
194154
{
195-
List<InputMethodSubtype> enabled_subtypes = getEnabledSubtypes(imm);
196-
InputMethodSubtype subtype = defaultSubtypes(imm, enabled_subtypes);
197-
if (subtype != null)
198-
{
199-
String s = subtype.getExtraValueOf("default_layout");
200-
if (s != null)
201-
default_layout = LayoutsPreference.layout_of_string(getResources(), s);
202-
refreshAccentsOption(imm, enabled_subtypes);
203-
}
155+
String layout_name = _device_locales.default_.default_layout;
156+
if (layout_name != null)
157+
default_layout = LayoutsPreference.layout_of_string(getResources(), layout_name);
204158
}
159+
_config.extra_keys_subtype = _device_locales.extra_keys();
205160
if (default_layout == null)
206161
default_layout = loadLayout(R.xml.latn_qwerty_us);
207162
_localeTextLayout = default_layout;
208163
}
209164

210-
private void refresh_candidates_view(EditorInfo info)
165+
private void refresh_candidates_view()
211166
{
212-
boolean should_show = CandidatesView.should_show(info);
213-
_config.should_show_candidates_view = should_show;
167+
boolean should_show = _config.editor_config.should_show_candidates_view;
214168
_candidates_view.setVisibility(should_show ? View.VISIBLE : View.GONE);
215169
}
216170

@@ -220,7 +174,6 @@ private void refresh_config()
220174
{
221175
int prev_theme = _config.theme;
222176
_config.refresh(getResources(), _foldStateTracker.isUnfolded());
223-
refreshSubtypeImm();
224177
// Refreshing the theme config requires re-creating the views
225178
if (prev_theme != _config.theme)
226179
{
@@ -252,7 +205,7 @@ public void onStartInputView(EditorInfo info, boolean restarting)
252205
{
253206
_config.editor_config.refresh(info, getResources());
254207
refresh_config();
255-
refresh_candidates_view(info);
208+
refresh_candidates_view();
256209
_currentSpecialLayout = refresh_special_layout();
257210
_keyboardView.setKeyboard(current_layout());
258211
_keyeventhandler.started(_config);
@@ -339,6 +292,7 @@ private static void updateLayoutGravityOf(final View view, final int layoutGravi
339292
public void onCurrentInputMethodSubtypeChanged(InputMethodSubtype subtype)
340293
{
341294
refreshSubtypeImm();
295+
refresh_candidates_view();
342296
_keyboardView.setKeyboard(current_layout());
343297
}
344298

0 commit comments

Comments
 (0)