Unexpected-Keyboard/srcs/juloo.keyboard2/Autocapitalisation.java
Jules Aguillon c778b4e8a2 Fix autocapitalisation randomly not triggered
The autocapitalisation is asking the editor about whether to enable
shift and must make sure to ask after the editor is done processing the
events.
2022-09-24 18:53:37 +02:00

132 lines
3.1 KiB
Java

package juloo.keyboard2;
import android.os.Handler;
import android.os.Looper;
import android.text.InputType;
import android.text.TextUtils;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.KeyEvent;
final class Autocapitalisation
{
boolean _enabled = false;
boolean _should_enable_shift = false;
boolean _should_disable_shift = false;
boolean _should_update_caps_mode = false;
Handler _handler;
InputConnection _ic;
Callback _callback;
int _caps_mode;
/** Keep track of the cursor to recognize cursor movements from typing. */
int _cursor;
static int SUPPORTED_CAPS_MODES =
InputType.TYPE_TEXT_FLAG_CAP_SENTENCES |
InputType.TYPE_TEXT_FLAG_CAP_WORDS;
Runnable delayed_callback = new Runnable()
{
public void run()
{
if (_should_update_caps_mode)
{
_should_enable_shift = _enabled && (_ic.getCursorCapsMode(_caps_mode) != 0);
_should_update_caps_mode = false;
}
_callback.update_shift_state(_should_enable_shift, _should_disable_shift);
}
};
void callback(final boolean might_disable)
{
_should_disable_shift = might_disable;
// The callback must be delayed because [getCursorCapsMode] would sometimes
// be called before the editor finished handling the previous event.
_handler.postDelayed(delayed_callback, 1);
}
/**
* The events are: started, typed, event sent, selection updated
* [started] does initialisation work and must be called before any other
* event.
*/
public void started(Looper looper, Callback cb, EditorInfo info, InputConnection ic)
{
_handler = new Handler(looper);
_ic = ic;
_callback = cb;
_caps_mode = info.inputType & TextUtils.CAP_MODE_SENTENCES;
if (!Config.globalConfig().autocapitalisation || _caps_mode == 0)
{
_enabled = false;
return;
}
_enabled = true;
_should_enable_shift = (info.initialCapsMode != 0);
_callback.update_shift_state(_should_enable_shift, true);
}
public void typed(CharSequence c)
{
for (int i = 0; i < c.length(); i++)
type_one_char(c.charAt(i));
callback(false);
}
public void typed(char c)
{
type_one_char(c);
callback(false);
}
void type_one_char(char c)
{
_cursor++;
if (is_trigger_character(c))
_should_update_caps_mode = true;
else
_should_enable_shift = false;
}
public void event_sent(int code)
{
switch (code)
{
case KeyEvent.KEYCODE_DEL:
if (_cursor > 0) _cursor--;
_should_update_caps_mode = true;
break;
}
callback(true);
}
/** Returns [true] if shift might be disabled. */
public void selection_updated(int old_cursor, int new_cursor)
{
if (new_cursor == _cursor) // Just typing
return;
_cursor = new_cursor;
_should_enable_shift = false;
callback(true);
}
boolean is_trigger_character(char c)
{
switch (c)
{
case ' ':
return true;
default:
return false;
}
}
public static interface Callback
{
public void update_shift_state(boolean should_enable, boolean should_disable);
}
}