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
109 changes: 91 additions & 18 deletions srcs/juloo.keyboard2/CurrentlyTypedWord.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package juloo.keyboard2;

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

/** Keep track of the word being typed. This also tracks whether the selection
Expand All @@ -24,11 +26,14 @@ public final class CurrentlyTypedWord
/** 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. */
/** The estimated cursor position in code points. 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;
/** The cursor position within the current word relative to the end of the
word in chars. Equal to [0] when the cursor is at the end of the word. */
int _w_cursor;

public CurrentlyTypedWord(Handler h, Callback cb)
{
Expand All @@ -46,15 +51,25 @@ public boolean is_selection_not_empty()
return _has_selection;
}

/** The cursor position relative to the end of the word. */
public int cursor_relative()
{
return _w_cursor;
}

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;
_w_cursor = 0;
if (!_has_selection)
{
set_current_word(e.initial_text_before_cursor);
_w_cursor = -append_chars(e.initial_text_after_cursor);
}
}

public void typed(String s)
Expand All @@ -70,12 +85,22 @@ 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))
if (!_enabled)
return;
_has_selection = new_has_sel;
_cursor = newSelStart;
refresh_current_word();
boolean new_has_sel = newSelStart != newSelEnd;
if (new_has_sel || _has_selection) // Selection was on or is now on.
{
_cursor = newSelStart;
_has_selection = new_has_sel;
refresh_current_word();
}
else if (newSelStart != _cursor)
{
_cursor = newSelStart;
_w_cursor += newSelStart - oldSelStart;
if (_w_cursor < -_w.length() || _w_cursor > 0)
refresh_current_word();
}
}

public void event_sent(int code, int meta)
Expand All @@ -87,31 +112,64 @@ public void event_sent(int code, int meta)

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

/** Estimate the currently typed word after [chars] has been typed. */
void type_chars(String s)
void type_chars(CharSequence s, int start, int end)
{
int len = s.length();
for (int i = 0; i < len;)
int insert_start = 0;
// Iterate over code points as that's the unit of [_cursor].
for (int i = start; i < end;)
{
int c = s.codePointAt(i);
if (Character.isLetter(c))
_w.appendCodePoint(c);
else
_w.setLength(0);
int c = Character.codePointAt(s, i);
i += Character.charCount(c);
_cursor++;
if (!Character.isLetter(c))
insert_start = i;
}
if (insert_start > 0)
_w.setLength(0);
_w.insert(_w.length() + _w_cursor, s, insert_start, end);
}

void type_chars(CharSequence s)
{
type_chars(s, 0, s.length());
}

/** Append chars to the current word without moving the cursor. Return the
number of characters that were added in the current word. */
int append_chars(CharSequence s, int start, int end)
{
int i = start;
while (i < end)
{
int c = Character.codePointAt(s, i);
if (!Character.isLetter(c))
break;
_w.appendCodePoint(c);
i += Character.charCount(c);
}
return i - start;
}

int append_chars(CharSequence s)
{
return append_chars(s, 0, s.length());
}

/** Refresh the current word by immediately querying the editor. */
void refresh_current_word()
{
Logs.debug("Refresh current word");
_refresh_pending = false;
_w_cursor = 0;
if (_has_selection)
set_current_word("");
else if (VERSION.SDK_INT >= 31)
set_current_word(_ic.getSurroundingText(20, 20, 0));
else
set_current_word(_ic.getTextBeforeCursor(20, 0));
}
Expand All @@ -128,6 +186,21 @@ void set_current_word(CharSequence text_before_cursor)
callback();
}

/** Like above but take the text after the cursor into account. */
void set_current_word(SurroundingText st)
{
_w.setLength(0);
if (st == null)
return;
int saved_cursor = _cursor;
int st_sel = st.getSelectionStart();
CharSequence st_text = st.getText();
type_chars(st_text, 0, st_sel);
_w_cursor = -append_chars(st_text, st_sel, st_text.length());
_cursor = saved_cursor;
callback();
}

/** Wait some time to let the editor finishes reacting to changes and call
[refresh_current_word]. */
void delayed_refresh()
Expand Down
6 changes: 5 additions & 1 deletion srcs/juloo.keyboard2/EditorConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public final class EditorConfig

/** CurrentlyTypedWord. */
public CharSequence initial_text_before_cursor = null; // Might be [null].
public CharSequence initial_text_after_cursor = null; // Might be [null].
public int initial_sel_start;
public int initial_sel_end;

Expand Down Expand Up @@ -92,7 +93,10 @@ public void refresh(EditorInfo info, Resources res)
caps_initially_updated = caps_should_update_state(info);
/* CurrentlyTypedWord */
if (VERSION.SDK_INT >= 30)
initial_text_before_cursor = info.getInitialTextBeforeCursor(10, 0);
{
initial_text_before_cursor = info.getInitialTextBeforeCursor(20, 0);
initial_text_after_cursor = info.getInitialTextAfterCursor(20, 0);
}
initial_sel_start = info.initialSelStart;
initial_sel_end = info.initialSelEnd;
/* Suggestions */
Expand Down
10 changes: 6 additions & 4 deletions srcs/juloo.keyboard2/KeyEventHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ public void mods_changed(Pointers.Modifiers mods)
public void suggestion_entered(String text)
{
String old = _typedword.get();
replace_text_before_cursor(old.length(), text + " ");
int cur_rel = _typedword.cursor_relative();
replace_surrounding_text(old.length() + cur_rel, -cur_rel, text + " ");
last_replaced_word = old;
last_replacement_word_len = text.length() + 1;
}
Expand Down Expand Up @@ -256,13 +257,14 @@ void send_text(String text)
clear_space_bar_state();
}

void replace_text_before_cursor(int remove_length, String new_text)
void replace_surrounding_text(int remove_before, int remove_after,
String new_text)
{
InputConnection conn = _recv.getCurrentInputConnection();
if (conn == null)
return;
conn.beginBatchEdit();
conn.deleteSurroundingText(remove_length, 0);
conn.deleteSurroundingText(remove_before, remove_after);
conn.commitText(new_text, 1);
conn.endBatchEdit();
}
Expand Down Expand Up @@ -540,7 +542,7 @@ void handle_backspace()
{
if (last_replaced_word != null)
{
replace_text_before_cursor(last_replacement_word_len,
replace_surrounding_text(last_replacement_word_len, 0,
last_replaced_word + " ");
last_replaced_word = null;
}
Expand Down
Loading