Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion res/layout/keyboard.xml
Original file line number Diff line number Diff line change
@@ -1,2 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<juloo.keyboard2.Keyboard2View xmlns:android="http://schemas.android.com/apk/res/android" android:hardwareAccelerated="false" android:background="?attr/colorKeyboard"/>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:hardwareAccelerated="false" android:orientation="vertical" android:background="?attr/colorKeyboard">
<juloo.keyboard2.CandidatesView android:id="@+id/candidates_view" android:layout_width="match_parent" android:layout_height="48dp" android:orientation="horizontal">
<TextView android:id="@+id/candidates_left" style="@style/candidates_item" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1"/>
<TextView android:id="@+id/candidates_middle" style="@style/candidates_item" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1"/>
<TextView android:id="@+id/candidates_right" style="@style/candidates_item" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1"/>
</juloo.keyboard2.CandidatesView>
<juloo.keyboard2.Keyboard2View android:id="@+id/keyboard_view" android:layout_width="match_parent" android:layout_height="wrap_content"/>
</LinearLayout>
6 changes: 6 additions & 0 deletions res/values/styles.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Candidates view -->
<style name="candidates_item">
<item name="android:gravity">center</item>
<item name="android:textSize">18sp</item>
<item name="android:textColor">?attr/colorLabel</item>
</style>
<!-- Emoji pane -->
<style name="emojiTypeButton">
<item name="android:padding">1px</item>
Expand Down
1 change: 1 addition & 0 deletions res/values/values.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<dimen name="emoji_text_size">28dp</dimen>
<dimen name="clipboard_view_height">300dp</dimen>
<dimen name="pref_button_size">28dp</dimen>
<dimen name="candidates_spacing">8dp</dimen>
<!-- Will be overwritten automatically by Gradle for the debug build variant -->
<bool name="debug_logs">false</bool>
</resources>
104 changes: 104 additions & 0 deletions srcs/juloo.keyboard2/CandidatesView.java
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
3 changes: 3 additions & 0 deletions srcs/juloo.keyboard2/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -101,6 +102,7 @@ private Config(SharedPreferences prefs, Resources res, IKeyEventHandler h, Boole
// from prefs
refresh(res, foldableUnfolded);
// initialized later
should_show_candidates_view = false;
shouldOfferVoiceTyping = false;
extra_keys_subtype = null;
handler = h;
Expand Down Expand Up @@ -291,6 +293,7 @@ public static interface IKeyEventHandler
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. */
Expand Down
149 changes: 149 additions & 0 deletions srcs/juloo.keyboard2/CurrentlyTypedWord.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
package juloo.keyboard2;

import android.os.Handler;
import android.view.KeyEvent;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import java.util.List;

/** Keep track of the word being typed. */
public final class CurrentlyTypedWord
{
InputConnection _ic = null;
Handler _handler;
Callback _callback;

/** The currently typed word. */
StringBuilder _w = new StringBuilder();
/** This can be disabled if the editor doesn't support looking at the text
before the cursor. */
boolean _enabled = false;
/** The current word is empty while the selection is ongoing. */
boolean _has_selection = false;
/** Used to avoid concurrent refreshes in [delayed_refresh()]. */
boolean _refresh_pending = false;

/** The estimated cursor position. Used to avoid expensive IPC calls when the
typed word can be estimated locally with [typed]. When the cursor
position gets out of sync, the text before the cursor is queried again to
the editor. */
int _cursor;

public CurrentlyTypedWord(Handler h, Callback cb)
{
_handler = h;
_callback = cb;
}

public String get()
{
return _w.toString();
}

public void started(Config conf, InputConnection ic)
{
_ic = ic;
_enabled = true;
EditorConfig e = conf.editor_config;
_has_selection = e.initial_sel_start != e.initial_sel_end;
_cursor = e.initial_sel_start;
if (!_has_selection)
set_current_word(e.initial_text_before_cursor);
}

public void typed(String s)
{
if (!_enabled)
return;
_has_selection = false;
type_chars(s);
callback();
}

public void selection_updated(int oldSelStart, int newSelStart, int newSelEnd)
{
// Avoid the expensive [refresh_current_word] call when [typed] was called
// before.
boolean new_has_sel = newSelStart != newSelEnd;
if (!_enabled || (newSelStart == _cursor && new_has_sel == _has_selection))
return;
_has_selection = new_has_sel;
_cursor = newSelStart;
refresh_current_word();
}

public void event_sent(int code, int meta)
{
if (!_enabled)
return;
delayed_refresh();
}

void callback()
{
_callback.currently_typed_word(_w.toString());
}

/** Estimate the currently typed word after [chars] has been typed. */
void type_chars(String s)
{
int len = s.length();
for (int i = 0; i < len;)
{
int c = s.codePointAt(i);
if (Character.isLetter(c))
_w.appendCodePoint(c);
else
_w.setLength(0);
_cursor++;
i += Character.charCount(c);
}
}

/** Refresh the current word by immediately querying the editor. */
void refresh_current_word()
{
_refresh_pending = false;
if (_has_selection)
set_current_word("");
else
set_current_word(_ic.getTextBeforeCursor(10, 0));
}

/** Refresh the current word by immediately querying the editor. */
void set_current_word(CharSequence text_before_cursor)
{
if (text_before_cursor == null)
{
_enabled = false;
return;
}
_w.setLength(0);
int saved_cursor = _cursor;
type_chars(text_before_cursor.toString());
_cursor = saved_cursor;
callback();
}

/** Wait some time to let the editor finishes reacting to changes and call
[refresh_current_word]. */
void delayed_refresh()
{
_refresh_pending = true;
_handler.postDelayed(delayed_refresh_run, 50);
}

Runnable delayed_refresh_run = new Runnable()
{
public void run()
{
if (_refresh_pending)
refresh_current_word();
}
};

public static interface Callback
{
public void currently_typed_word(String word);
}
}
9 changes: 9 additions & 0 deletions srcs/juloo.keyboard2/EditorConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ public final class EditorConfig
// Whether caps state should be updated right away.
public boolean caps_initially_updated = false;

/** CurrentlyTypedWord. */
public CharSequence initial_text_before_cursor = null;
public int initial_sel_start;
public int initial_sel_end;

public EditorConfig() {}

public void refresh(EditorInfo info, Resources res)
Expand Down Expand Up @@ -66,6 +71,10 @@ public void refresh(EditorInfo info, Resources res)
caps_mode = info.inputType & TextUtils.CAP_MODE_SENTENCES;
caps_initially_enabled = (info.initialCapsMode != 0);
caps_initially_updated = caps_should_update_state(info);
/* CurrentlyTypedWord */
initial_text_before_cursor = info.getInitialTextBeforeCursor(10, 0);
initial_sel_start = info.initialSelStart;
initial_sel_end = info.initialSelEnd;
}

String actionLabel_of_imeAction(int action, Resources res)
Expand Down
Loading