From b14e25dfa5d9ecce33e80325e17273674792578f Mon Sep 17 00:00:00 2001 From: William Casarin Date: Mon, 30 Jun 2025 11:57:28 -0700 Subject: [PATCH 1/3] 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 --- android-activity/src/game_activity/mod.rs | 23 +- android-activity/src/lib.rs | 224 ++++++++++++++++++++ android-activity/src/native_activity/mod.rs | 8 +- 3 files changed, 253 insertions(+), 2 deletions(-) diff --git a/android-activity/src/game_activity/mod.rs b/android-activity/src/game_activity/mod.rs index 95747c0..80972e2 100644 --- a/android-activity/src/game_activity/mod.rs +++ b/android-activity/src/game_activity/mod.rs @@ -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, diff --git a/android-activity/src/lib.rs b/android-activity/src/lib.rs index 51c63b8..ad47c6b 100644 --- a/android-activity/src/lib.rs +++ b/android-activity/src/lib.rs @@ -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}.

IME authors: If you do not recognize the + /// variation, normal should be assumed.

+ 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 diff --git a/android-activity/src/native_activity/mod.rs b/android-activity/src/native_activity/mod.rs index 27a25d5..14ce1ec 100644 --- a/android-activity/src/native_activity/mod.rs +++ b/android-activity/src/native_activity/mod.rs @@ -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 { let mut guard = self.key_maps.lock().unwrap(); From f344b4202bf267b381b50aeb2595b9118227abac Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Sat, 21 Feb 2026 00:56:31 +0000 Subject: [PATCH 2/3] move ImeOptions + InputType to src/input.rs + fills out This adds and documents the remaining `ImeOptions` (addressing TODO comment) `ImeOptions` now has a getter/setter for the action, based on the `TextInputAction` enum added in #216 There is also a separate `InputTypeClass` that lets you query the mutually-exclusive type class bits from an `InputType` --- android-activity/src/game_activity/mod.rs | 9 +- android-activity/src/input.rs | 372 ++++++++++++++++++++ android-activity/src/lib.rs | 218 +----------- android-activity/src/native_activity/mod.rs | 9 +- 4 files changed, 383 insertions(+), 225 deletions(-) diff --git a/android-activity/src/game_activity/mod.rs b/android-activity/src/game_activity/mod.rs index 80972e2..0308dbd 100644 --- a/android-activity/src/game_activity/mod.rs +++ b/android-activity/src/game_activity/mod.rs @@ -23,20 +23,21 @@ use ndk::configuration::Configuration; use ndk::native_window::NativeWindow; use crate::error::InternalResult; -use crate::input::{device_key_character_map, Axis, KeyCharacterMap, TextInputAction}; use crate::util::{ abort_on_panic, forward_stdio_to_logcat, init_android_main_thread, log_panic, try_get_path_from_ptr, }; use crate::{ - AndroidApp, ConfigurationRef, ImeOptions, InputStatus, InputType, MainEvent, PollEvent, Rect, - WindowManagerFlags, + AndroidApp, ConfigurationRef, InputStatus, MainEvent, PollEvent, Rect, WindowManagerFlags, }; mod ffi; pub mod input; -use crate::input::{TextInputState, TextSpan}; +use crate::input::{ + device_key_character_map, Axis, ImeOptions, InputType, KeyCharacterMap, TextInputAction, + TextInputState, TextSpan, +}; use input::{InputEvent, KeyEvent, MotionEvent}; // The only time it's safe to update the android_app->savedState pointer is diff --git a/android-activity/src/input.rs b/android-activity/src/input.rs index aae6292..2820b7f 100644 --- a/android-activity/src/input.rs +++ b/android-activity/src/input.rs @@ -934,6 +934,378 @@ pub enum TextInputAction { __Unknown(i32), } +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 { + + /// The mask of bits that configure alternative actions for the "enter" key. This helps the + /// IME provide clear feedback for what the key will do and provide alternative mechanisms + /// for taking the same action. + const IME_MASK_ACTION = 0x000000ff; + + /// Indicates that ascii input is a priority (such as for entering an account ID) + const IME_FLAG_FORCE_ASCII = 0x80000000; + + /// Indicates that it's possible to navigate focus forwards to something. + /// + /// This is similar to using `IME_ACTION_NEXT` except it allows for multi-line input with + /// an enter key in addition to forward navigation for focus. + /// + /// This may not be supported by all IMEs (especially on small screens) + const IME_FLAG_NAVIGATE_NEXT = 0x08000000; + + /// Similar to `IME_FLAG_NAVIGATE_NEXT`, except it indicates that it's possible to navigate + /// focus backwards to something. + const IME_FLAG_NAVIGATE_PREVIOUS = 0x04000000; + + /// This requests that the IME should not show any accessory actions next to the extracted + /// text UI, when it is in fullscreen mode. + /// + /// The implication is that you think it's more important to prioritize having room for + /// previewing more text, instead of showing accessory actions. + /// + /// Note: In some cases this can make the action unavailable. + const IME_FLAG_NO_ACCESSORY_ACTION = 0x20000000; + + /// 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 = 0x40000000; + + /// Don't show any "extracted-text UI" as part of the on-screen IME. + /// + /// Some keyboards may show an additional text box above the keyboard for previewing what + /// you type (referred to as the extracted text UI) and it can sometimes be quite large. + /// + /// The exact semantics of this flag can be unclear sometimes and the UI that becomes + /// visible may not respond to input as you would expect. + /// + /// This flag may be deprecated in the future and it's recommend to use + /// `IME_FLAG_NO_FULLSCREEN` instead, to avoid having the extracted text UI appear to cover + /// the full screen. + const IMG_FLAG_NO_EXTRACT_UI = 0x10000000; + + /// Request that the IME should avoid ever entering a fullscreen mode and should always + /// leave some room for the application UI. + /// + /// Note: It's not guaranteed that an IME will honor this state + const IME_FLAG_NO_FULLSCREEN = 0x02000000; + + /// Request that the IME should not update personalized data, such as typing history. + /// + /// Note: It's not guaranteed that an IME will honor this state + const IME_FLAG_NO_PERSONALIZED_LEARNING = 0x01000000; + + /// Generic unspecified type for ImeOptions + const IME_NULL = 0; + } +} + +impl ImeOptions { + /// Specify what action the IME's "enter" key should perform. + /// + /// This helps the IME provide clear feedback for what the key will do and provide alternative + /// mechanisms for taking the same action. + pub fn set_action(&mut self, action: TextInputAction) { + let action: i32 = action.into(); + let action = action as u32; + *self = Self::from_bits_truncate( + (self.bits() & !Self::IME_MASK_ACTION.bits()) | (action & Self::IME_MASK_ACTION.bits()), + ); + } + + /// Get the current action of the IME's "enter" key. + pub fn action(&self) -> TextInputAction { + let action_bits = self.bits() & Self::IME_MASK_ACTION.bits(); + TextInputAction::from(action_bits as i32) + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, num_enum::FromPrimitive, num_enum::IntoPrimitive)] +#[non_exhaustive] +#[repr(u32)] +pub enum InputTypeClass { + /// 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. + 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 + /// - TYPE_TEXT_FLAG_CAP_SENTENCES. + /// + /// It also supports the following variations: + /// - TYPE_TEXT_VARIATION_NORMAL + /// - TYPE_TEXT_VARIATION_URI + /// + /// *If you do not recognize the variation, normal should be assumed.* + Text = 1, + + /// Class for numeric text. + /// + /// This class supports the following flags: + /// - `TYPE_NUMBER_FLAG_SIGNED` + /// - `TYPE_NUMBER_FLAG_DECIMAL` + /// + /// It also supports the following variations: + /// - `TYPE_NUMBER_VARIATION_NORMAL` + /// - `TYPE_NUMBER_VARIATION_PASSWORD` + /// + /// *IME authors: If you do not recognize the variation, normal should be assumed.* + Number = 2, + + /// Class for a phone number. + /// + /// This class currently supports no variations or flags. + Phone = 3, + + /// Class for dates and times. + /// + /// It supports the following variations: + /// - TYPE_DATETIME_VARIATION_NORMAL + /// - TYPE_DATETIME_VARIATION_DATE + /// - TYPE_DATETIME_VARIATION_TIME + DateTime = 4, + + #[doc(hidden)] + #[num_enum(catch_all)] + __Unknown(u32), +} + +bitflags! { + /// Flags specifying the content type of text being input. + /// + /// Corresponds to the Android SDK [InputType](https://developer.android.com/reference/android/text/InputType) API + #[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 = 0x0000000f; + + /// Mask of bits that determine the variation of the base content class. + const TYPE_MASK_VARIATION = 0x00000ff0; + + /// Mask of bits that provide addition bit flags of options. + const TYPE_MASK_FLAGS = 0x00fff000; + + /// 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 = 0x00001000; + + /// 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 = 0x00002000; + + /// 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 = 0x00004000; + + /// 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 = 0x00008000; + + /// 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 = 0x00010000; + + /// 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 = 0x00020000; + + /// 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 = 0x00040000; + + /// 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 = 0x00080000; + + /// 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 = 0x00100000; + + /// Flag for TYPE_CLASS_TEXT: Let the IME know that conversion candidate selection + /// information is requested by the application. Text conversion suggestion is for the + /// transliteration languages, which have the notions of pronunciation and target + /// characters. When the user actively selects a candidate from the conversion suggestions, + /// notifying when candidate selection is occurring helps assistive technologies generate + /// more effective feedback. When this flag is set, and there is an active selected + /// suggestion, the IME should set that a conversion suggestion is selected when + /// initializing the TextAttribute. To receive this information, the application should + /// implement InputConnection.setComposingText(CharSequence, int, TextAttribute), + /// InputConnection.setComposingRegion(int, int, TextAttribute), and + /// InputConnection.commitText(CharSequence, int, TextAttribute) + const TYPE_TEXT_FLAG_ENABLE_TEXT_SUGGESTION_SELECTED = 0x00200000; + + /// 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 = 0x00000010; + /// Variation of TYPE_CLASS_TEXT: entering an e-mail address. + const TYPE_TEXT_VARIATION_EMAIL_ADDRESS = 0x00000020; + /// Variation of TYPE_CLASS_TEXT: entering the subject line of an e-mail. + const TYPE_TEXT_VARIATION_EMAIL_SUBJECT = 0x00000030; + /// 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 = 0x00000050; + /// Variation of TYPE_CLASS_TEXT: entering the name of a person. + const TYPE_TEXT_VARIATION_PERSON_NAME = 0x00000060; + /// Variation of TYPE_CLASS_TEXT: entering a postal mailing address. + const TYPE_TEXT_VARIATION_POSTAL_ADDRESS = 0x00000070; + /// Variation of TYPE_CLASS_TEXT: entering a password. + const TYPE_TEXT_VARIATION_PASSWORD = 0x00000080; + /// Variation of TYPE_CLASS_TEXT: entering a password, which should be visible to the user. + const TYPE_TEXT_VARIATION_VISIBLE_PASSWORD = 0x00000090; + /// Variation of TYPE_CLASS_TEXT: entering text inside of a web form. + const TYPE_TEXT_VARIATION_WEB_EDIT_TEXT = 0x000000a0; + /// Variation of TYPE_CLASS_TEXT: entering text to filter contents of a list etc. + const TYPE_TEXT_VARIATION_FILTER = 0x000000b0; + /// 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 = 0x000000c0; + /// 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 = 0x000000d0; + /// 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 = 0x000000e0; + /// 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}.

IME authors: If you do not recognize the + /// variation, normal should be assumed.

+ 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 = 0x00001000; + /// Flag of TYPE_CLASS_NUMBER: the number is decimal, allowing a decimal point to + /// provide fractional values. + const TYPE_NUMBER_FLAG_DECIMAL = 0x00002000; + /// 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 = 0x00000010; + /// 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; + + } +} + +impl InputType { + /// Extract just the class of the input type. + pub fn class(&self) -> InputTypeClass { + let class = self.bits() & InputType::TYPE_MASK_CLASS.bits(); + InputTypeClass::from(class) + } +} + /// An exclusive, lending iterator for input events pub struct InputIterator<'a> { pub(crate) inner: crate::activity_impl::InputIteratorInner<'a>, diff --git a/android-activity/src/lib.rs b/android-activity/src/lib.rs index ad47c6b..a5d2ec3 100644 --- a/android-activity/src/lib.rs +++ b/android-activity/src/lib.rs @@ -346,222 +346,6 @@ 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}.

IME authors: If you do not recognize the - /// variation, normal should be assumed.

- 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) @@ -943,7 +727,7 @@ impl AndroidApp { } /// Set IME editor flags - pub fn set_ime_editor_info(&self, input_type: InputType, options: ImeOptions) { + pub fn set_ime_editor_info(&self, input_type: input::InputType, options: input::ImeOptions) { self.inner .read() .unwrap() diff --git a/android-activity/src/native_activity/mod.rs b/android-activity/src/native_activity/mod.rs index 14ce1ec..0130c37 100644 --- a/android-activity/src/native_activity/mod.rs +++ b/android-activity/src/native_activity/mod.rs @@ -13,14 +13,15 @@ use ndk::input_queue::InputQueue; use ndk::{asset::AssetManager, native_window::NativeWindow}; use crate::error::InternalResult; -use crate::input::{device_key_character_map, Axis, KeyCharacterMap}; -use crate::input::{TextInputState, TextSpan}; use crate::{ - util, AndroidApp, ConfigurationRef, ImeOptions, InputStatus, InputType, MainEvent, PollEvent, - Rect, WindowManagerFlags, + util, AndroidApp, ConfigurationRef, InputStatus, MainEvent, PollEvent, Rect, WindowManagerFlags, }; pub mod input; +use crate::input::{ + device_key_character_map, Axis, ImeOptions, InputType, KeyCharacterMap, TextInputState, + TextSpan, +}; mod glue; use self::glue::NativeActivityGlue; From 5781e29470511a59286d12c6c6bcbae74cef47fa Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Mon, 2 Mar 2026 15:41:26 +0000 Subject: [PATCH 3/3] set_ime_editor_info: accept an 'action: TextInputAction' arg Makes it possible to configure the action of the IME enter key via `set_ime_editor_info()` --- android-activity/src/game_activity/mod.rs | 23 ++++++++++++++------- android-activity/src/lib.rs | 15 +++++++++++--- android-activity/src/native_activity/mod.rs | 11 +++++++--- 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/android-activity/src/game_activity/mod.rs b/android-activity/src/game_activity/mod.rs index 0308dbd..53889cf 100644 --- a/android-activity/src/game_activity/mod.rs +++ b/android-activity/src/game_activity/mod.rs @@ -214,17 +214,20 @@ impl NativeAppGlue { self.text_input_state() } - pub fn set_ime_editor_info(&self, input_type: InputType, options: ImeOptions) { + pub fn set_ime_editor_info( + &self, + input_type: InputType, + action: TextInputAction, + 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? + let action_id: i32 = action.into(); ffi::GameActivity_setImeEditorInfo( activity, input_type.bits(), - action_id, + action_id as _, options.bits(), ); } @@ -579,8 +582,14 @@ 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 fn set_ime_editor_info( + &self, + input_type: InputType, + action: TextInputAction, + options: ImeOptions, + ) { + self.native_app + .set_ime_editor_info(input_type, action, options); } pub(crate) fn device_key_character_map( diff --git a/android-activity/src/lib.rs b/android-activity/src/lib.rs index a5d2ec3..f9298fa 100644 --- a/android-activity/src/lib.rs +++ b/android-activity/src/lib.rs @@ -726,12 +726,21 @@ impl AndroidApp { self.inner.read().unwrap().set_text_input_state(state); } - /// Set IME editor flags - pub fn set_ime_editor_info(&self, input_type: input::InputType, options: input::ImeOptions) { + /// Specify the type of text being input, how the IME enter/action key + /// should behave and any additional IME options. + /// + /// Also see the Android SDK documentation for + /// [android.view.inputmethod.EditorInfo](https://developer.android.com/reference/android/view/inputmethod/EditorInfo) + pub fn set_ime_editor_info( + &self, + input_type: input::InputType, + action: input::TextInputAction, + options: input::ImeOptions, + ) { self.inner .read() .unwrap() - .set_ime_editor_info(input_type, options); + .set_ime_editor_info(input_type, action, options); } /// Get an exclusive, lending iterator over buffered input events diff --git a/android-activity/src/native_activity/mod.rs b/android-activity/src/native_activity/mod.rs index 0130c37..74f2925 100644 --- a/android-activity/src/native_activity/mod.rs +++ b/android-activity/src/native_activity/mod.rs @@ -19,8 +19,8 @@ use crate::{ pub mod input; use crate::input::{ - device_key_character_map, Axis, ImeOptions, InputType, KeyCharacterMap, TextInputState, - TextSpan, + device_key_character_map, Axis, ImeOptions, InputType, KeyCharacterMap, TextInputAction, + TextInputState, TextSpan, }; mod glue; @@ -387,7 +387,12 @@ impl AndroidAppInner { } // TODO: move into a trait - pub fn set_ime_editor_info(&self, _input_type: InputType, _options: ImeOptions) { + pub fn set_ime_editor_info( + &self, + _input_type: InputType, + _action: TextInputAction, + _options: ImeOptions, + ) { // NOP: Unsupported }