input: add set_ime_editor_info

This corresponds to the GameActivity_setImeEditorInfo function on
GameActivity. This is not supported on NativeActivity.

Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
William Casarin
2025-06-30 11:57:28 -07:00
committed by Robert Bragg
parent 483164c333
commit fdcf4ce28d
3 changed files with 253 additions and 2 deletions
+22 -1
View File
@@ -29,7 +29,8 @@ use crate::util::{
try_get_path_from_ptr,
};
use crate::{
AndroidApp, ConfigurationRef, InputStatus, MainEvent, PollEvent, Rect, WindowManagerFlags,
AndroidApp, ConfigurationRef, ImeOptions, InputStatus, InputType, MainEvent, PollEvent, Rect,
WindowManagerFlags,
};
mod ffi;
@@ -212,6 +213,22 @@ impl NativeAppGlue {
self.text_input_state()
}
pub fn set_ime_editor_info(&self, input_type: InputType, options: ImeOptions) {
unsafe {
let activity = (*self.as_ptr()).activity;
let action_id = 0; // IME_ACTION_UNSPECIFIED
// (https://developer.android.com/reference/android/view/inputmethod/EditorInfo#IME_ACTION_DONE)
// TODO: expose this later?
ffi::GameActivity_setImeEditorInfo(
activity,
input_type.bits(),
action_id,
options.bits(),
);
}
}
// TODO: move into a trait
pub fn set_text_input_state(&self, state: TextInputState) {
unsafe {
@@ -561,6 +578,10 @@ impl AndroidAppInner {
self.native_app.set_text_input_state(state);
}
pub fn set_ime_editor_info(&self, input_type: InputType, options: ImeOptions) {
self.native_app.set_ime_editor_info(input_type, options);
}
pub(crate) fn device_key_character_map(
&self,
device_id: i32,
+224
View File
@@ -346,6 +346,222 @@ pub enum InputStatus {
use activity_impl::AndroidAppInner;
pub use activity_impl::AndroidAppWaker;
bitflags! {
/// Flags for [`AndroidApp::set_ime_editor_info`]
/// as per the [android.view.inputmethod.EditorInfo Java API](https://developer.android.com/reference/android/view/inputmethod/EditorInfo)
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct ImeOptions: u32 {
/// If this flag is not set, IMEs will normally replace the "enter" key with the action
/// supplied. This flag indicates that the action should not be available in-line as a
/// replacement for the "enter" key. Typically this is because the action has such a
/// significant impact or is not recoverable enough that accidentally hitting it should be
/// avoided, such as sending a message.
const IME_FLAG_NO_ENTER_ACTION = 1073741824;
/// Generic unspecified type for ImeOptions
const IME_NULL = 0;
// TODO: remaining ime flags
}
}
bitflags! {
/// Flags for [`AndroidApp::set_ime_editor_info`]
/// as per the [android.view.inputmethod.EditorInfo Java API](https://developer.android.com/reference/android/view/inputmethod/EditorInfo)
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct InputType: u32 {
/// Mask of bits that determine the overall class of text being given. Currently
/// supported classes are: TYPE_CLASS_TEXT, TYPE_CLASS_NUMBER, TYPE_CLASS_PHONE,
/// TYPE_CLASS_DATETIME. IME authors: If the class is not one you understand, assume
/// TYPE_CLASS_TEXT with NO variation or flags.
const TYPE_MASK_CLASS = 15;
/// Mask of bits that determine the variation of the base content class.
const TYPE_MASK_VARIATION = 4080;
/// Mask of bits that provide addition bit flags of options.
const TYPE_MASK_FLAGS = 16773120;
/// Special content type for when no explicit type has been specified. This should be
/// interpreted to mean that the target input connection is not rich, it can not process
/// and show things like candidate text nor retrieve the current text, so the input
/// method will need to run in a limited "generate key events" mode, if it supports
/// it. Note that some input methods may not support it, for example a voice-based
/// input method will likely not be able to generate key events even if this flag is
/// set.
const TYPE_NULL = 0;
/// Class for normal text. This class supports the following flags (only one of which
/// should be set): TYPE_TEXT_FLAG_CAP_CHARACTERS, TYPE_TEXT_FLAG_CAP_WORDS, and.
/// TYPE_TEXT_FLAG_CAP_SENTENCES. It also supports the following variations:
/// TYPE_TEXT_VARIATION_NORMAL, and TYPE_TEXT_VARIATION_URI. If you do not recognize the
/// variation, normal should be assumed.
const TYPE_CLASS_TEXT = 1;
/// Flag for TYPE_CLASS_TEXT: capitalize all characters. Overrides
/// #TYPE_TEXT_FLAG_CAP_WORDS} and #TYPE_TEXT_FLAG_CAP_SENTENCES}. This value is
/// explicitly defined to be the same as TextUtils#CAP_MODE_CHARACTERS}. Of
/// course, this only affects languages where there are upper-case and lower-case
/// letters.
const TYPE_TEXT_FLAG_CAP_CHARACTERS = 4096;
/// Flag for TYPE_CLASS_TEXT: capitalize the first character of every word.
/// Overrides TYPE_TEXT_FLAG_CAP_SENTENCES. This value is explicitly defined
/// to be the same as TextUtils#CAP_MODE_WORDS. Of course, this only affects
/// languages where there are upper-case and lower-case letters.
const TYPE_TEXT_FLAG_CAP_WORDS = 8192;
/// Flag for TYPE_CLASS_TEXT: capitalize the first character of each sentence. This value
/// is explicitly defined to be the same as TextUtils#CAP_MODE_SENTENCES. For example in
/// English it means to capitalize after a period and a space (note that other languages
/// may have different characters for period, or not use spaces, or use different
/// grammatical rules). Of course, this only affects languages where there are upper-case
/// and lower-case letters.
const TYPE_TEXT_FLAG_CAP_SENTENCES = 16384;
/// Flag for TYPE_CLASS_TEXT: the user is entering free-form text that should have
/// auto-correction applied to it. Without this flag, the IME will not try to correct
/// typos. You should always set this flag unless you really expect users to type
/// non-words in this field, for example to choose a name for a character in a game.
/// Contrast this with TYPE_TEXT_FLAG_AUTO_COMPLETE and TYPE_TEXT_FLAG_NO_SUGGESTIONS:
/// TYPE_TEXT_FLAG_AUTO_CORRECT means that the IME will try to auto-correct typos as the
/// user is typing, but does not define whether the IME offers an interface to show
/// suggestions.
const TYPE_TEXT_FLAG_AUTO_CORRECT = 32768;
/// Flag for TYPE_CLASS_TEXT: the text editor (which means the application) is performing
/// auto-completion of the text being entered based on its own semantics, which it will
/// present to the user as they type. This generally means that the input method should
/// not be showing candidates itself, but can expect the editor to supply its own
/// completions/candidates from
/// android.view.inputmethod.InputMethodSession#displayCompletions
/// InputMethodSession.displayCompletions()} as a result of the editor calling
/// android.view.inputmethod.InputMethodManager#displayCompletions
/// InputMethodManager.displayCompletions()}. Note the contrast with
/// TYPE_TEXT_FLAG_AUTO_CORRECT and TYPE_TEXT_FLAG_NO_SUGGESTIONS:
/// TYPE_TEXT_FLAG_AUTO_COMPLETE means the editor should show an interface for displaying
/// suggestions, but instead of supplying its own it will rely on the Editor to pass
/// completions/corrections.
const TYPE_TEXT_FLAG_AUTO_COMPLETE = 65536;
/// Flag for TYPE_CLASS_TEXT: multiple lines of text can be entered into the
/// field. If this flag is not set, the text field will be constrained to a single
/// line. The IME may also choose not to display an enter key when this flag is not set,
/// as there should be no need to create new lines.
const TYPE_TEXT_FLAG_MULTI_LINE = 131072;
/// Flag for TYPE_CLASS_TEXT: the regular text view associated with this should
/// not be multi-line, but when a fullscreen input method is providing text it should
/// use multiple lines if it can.
const TYPE_TEXT_FLAG_IME_MULTI_LINE = 262144;
/// Flag for TYPE_CLASS_TEXT: the input method does not need to display any
/// dictionary-based candidates. This is useful for text views that do not contain words
/// from the language and do not benefit from any dictionary-based completions or
/// corrections. It overrides the TYPE_TEXT_FLAG_AUTO_CORRECT value when set. Please
/// avoid using this unless you are certain this is what you want. Many input methods need
/// suggestions to work well, for example the ones based on gesture typing. Consider
/// clearing TYPE_TEXT_FLAG_AUTO_CORRECT instead if you just do not want the IME to
/// correct typos. Note the contrast with TYPE_TEXT_FLAG_AUTO_CORRECT and
/// TYPE_TEXT_FLAG_AUTO_COMPLETE: TYPE_TEXT_FLAG_NO_SUGGESTIONS means the IME does not
/// need to show an interface to display suggestions. Most IMEs will also take this to
/// mean they do not need to try to auto-correct what the user is typing.
const TYPE_TEXT_FLAG_NO_SUGGESTIONS = 524288;
/// Flag for TYPE_CLASS_TEXT: Let the IME know the text conversion suggestions are
/// required by the application. Text conversion suggestion is for the transliteration
/// languages which has pronunciation characters and target characters. When the user is
/// typing the pronunciation charactes, the IME could provide the possible target
/// characters to the user. When this flag is set, the IME should insert the text
/// conversion suggestions through Builder#setTextConversionSuggestions(List)} and the
/// TextAttribute} with initialized with the text conversion suggestions is provided by
/// the IME to the application. To receive the additional information, the application
/// needs to implement InputConnection#setComposingText(CharSequence, int,
/// TextAttribute)}, InputConnection#setComposingRegion(int, int, TextAttribute)}, and
/// InputConnection#commitText(CharSequence, int, TextAttribute)}.
const TYPE_TEXT_FLAG_ENABLE_TEXT_CONVERSION_SUGGESTIONS = 1048576;
/// Default variation of TYPE_CLASS_TEXT: plain old normal text.
const TYPE_TEXT_VARIATION_NORMAL = 0;
/// Variation of TYPE_CLASS_TEXT: entering a URI.
const TYPE_TEXT_VARIATION_URI = 16;
/// Variation of TYPE_CLASS_TEXT: entering an e-mail address.
const TYPE_TEXT_VARIATION_EMAIL_ADDRESS = 32;
/// Variation of TYPE_CLASS_TEXT: entering the subject line of an e-mail.
const TYPE_TEXT_VARIATION_EMAIL_SUBJECT = 48;
/// Variation of TYPE_CLASS_TEXT: entering a short, possibly informal message such as an instant message or a text message.
const TYPE_TEXT_VARIATION_SHORT_MESSAGE = 64;
/// Variation of TYPE_CLASS_TEXT: entering the content of a long, possibly formal message such as the body of an e-mail.
const TYPE_TEXT_VARIATION_LONG_MESSAGE = 80;
/// Variation of TYPE_CLASS_TEXT: entering the name of a person.
const TYPE_TEXT_VARIATION_PERSON_NAME = 96;
/// Variation of TYPE_CLASS_TEXT: entering a postal mailing address.
const TYPE_TEXT_VARIATION_POSTAL_ADDRESS = 112;
/// Variation of TYPE_CLASS_TEXT: entering a password.
const TYPE_TEXT_VARIATION_PASSWORD = 128;
/// Variation of TYPE_CLASS_TEXT: entering a password, which should be visible to the user.
const TYPE_TEXT_VARIATION_VISIBLE_PASSWORD = 144;
/// Variation of TYPE_CLASS_TEXT: entering text inside of a web form.
const TYPE_TEXT_VARIATION_WEB_EDIT_TEXT = 160;
/// Variation of TYPE_CLASS_TEXT: entering text to filter contents of a list etc.
const TYPE_TEXT_VARIATION_FILTER = 176;
/// Variation of TYPE_CLASS_TEXT: entering text for phonetic pronunciation, such as a
/// phonetic name field in contacts. This is mostly useful for languages where one
/// spelling may have several phonetic readings, like Japanese.
const TYPE_TEXT_VARIATION_PHONETIC = 192;
/// Variation of TYPE_CLASS_TEXT: entering e-mail address inside of a web form. This
/// was added in android.os.Build.VERSION_CODES#HONEYCOMB}. An IME must target this API
/// version or later to see this input type; if it doesn't, a request for this type will
/// be seen as #TYPE_TEXT_VARIATION_EMAIL_ADDRESS} when passed through
/// android.view.inputmethod.EditorInfo#makeCompatible(int)
/// EditorInfo.makeCompatible(int)}.
const TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS = 208;
/// Variation of TYPE_CLASS_TEXT: entering password inside of a web form. This was
/// added in android.os.Build.VERSION_CODES#HONEYCOMB}. An IME must target this API
/// version or later to see this input type; if it doesn't, a request for this type will
/// be seen as #TYPE_TEXT_VARIATION_PASSWORD} when passed through
/// android.view.inputmethod.EditorInfo#makeCompatible(int)
/// EditorInfo.makeCompatible(int)}.
const TYPE_TEXT_VARIATION_WEB_PASSWORD = 224;
/// Class for numeric text. This class supports the following flags:
/// #TYPE_NUMBER_FLAG_SIGNED} and #TYPE_NUMBER_FLAG_DECIMAL}. It also supports the
/// following variations: #TYPE_NUMBER_VARIATION_NORMAL} and
/// #TYPE_NUMBER_VARIATION_PASSWORD}. <p>IME authors: If you do not recognize the
/// variation, normal should be assumed.</p>
const TYPE_CLASS_NUMBER = 2;
/// Flag of TYPE_CLASS_NUMBER: the number is signed, allowing a positive or negative
/// sign at the start.
const TYPE_NUMBER_FLAG_SIGNED = 4096;
/// Flag of TYPE_CLASS_NUMBER: the number is decimal, allowing a decimal point to
/// provide fractional values.
const TYPE_NUMBER_FLAG_DECIMAL = 8192;
/// Default variation of TYPE_CLASS_NUMBER: plain normal numeric text. This was added
/// in android.os.Build.VERSION_CODES#HONEYCOMB}. An IME must target this API version or
/// later to see this input type; if it doesn't, a request for this type will be dropped
/// when passed through android.view.inputmethod.EditorInfo#makeCompatible(int)
/// EditorInfo.makeCompatible(int)}.
const TYPE_NUMBER_VARIATION_NORMAL = 0;
/// Variation of TYPE_CLASS_NUMBER: entering a numeric password. This was added in
/// android.os.Build.VERSION_CODES#HONEYCOMB}. An IME must target this API version or
/// later to see this input type; if it doesn't, a request for this type will be dropped
/// when passed through android.view.inputmethod.EditorInfo#makeCompatible(int)
/// EditorInfo.makeCompatible(int)}.
const TYPE_NUMBER_VARIATION_PASSWORD = 16;
/// Class for a phone number. This class currently supports no variations or flags.
const TYPE_CLASS_PHONE = 3;
/// Class for dates and times. It supports the following variations:
/// #TYPE_DATETIME_VARIATION_NORMAL} #TYPE_DATETIME_VARIATION_DATE}, and
/// #TYPE_DATETIME_VARIATION_TIME}.
const TYPE_CLASS_DATETIME = 4;
/// Default variation of #TYPE_CLASS_DATETIME}: allows entering both a date and time.
const TYPE_DATETIME_VARIATION_NORMAL = 0;
/// Default variation of #TYPE_CLASS_DATETIME}: allows entering only a date.
const TYPE_DATETIME_VARIATION_DATE = 16;
/// Default variation of #TYPE_CLASS_DATETIME}: allows entering only a time.
const TYPE_DATETIME_VARIATION_TIME = 32;
}
}
bitflags! {
/// Flags for [`AndroidApp::set_window_flags`]
/// as per the [android.view.WindowManager.LayoutParams Java API](https://developer.android.com/reference/android/view/WindowManager.LayoutParams)
@@ -726,6 +942,14 @@ impl AndroidApp {
self.inner.read().unwrap().set_text_input_state(state);
}
/// Set IME editor flags
pub fn set_ime_editor_info(&self, input_type: InputType, options: ImeOptions) {
self.inner
.read()
.unwrap()
.set_ime_editor_info(input_type, options);
}
/// Get an exclusive, lending iterator over buffered input events
///
/// Applications are expected to call this in-sync with their rendering or
+7 -1
View File
@@ -16,7 +16,8 @@ use crate::error::InternalResult;
use crate::input::{device_key_character_map, Axis, KeyCharacterMap};
use crate::input::{TextInputState, TextSpan};
use crate::{
util, AndroidApp, ConfigurationRef, InputStatus, MainEvent, PollEvent, Rect, WindowManagerFlags,
util, AndroidApp, ConfigurationRef, ImeOptions, InputStatus, InputType, MainEvent, PollEvent,
Rect, WindowManagerFlags,
};
pub mod input;
@@ -384,6 +385,11 @@ impl AndroidAppInner {
// NOP: Unsupported
}
// TODO: move into a trait
pub fn set_ime_editor_info(&self, _input_type: InputType, _options: ImeOptions) {
// NOP: Unsupported
}
pub fn device_key_character_map(&self, device_id: i32) -> InternalResult<KeyCharacterMap> {
let mut guard = self.key_maps.lock().unwrap();