@@ -21,7 +21,7 @@ use ndk::configuration::Configuration;
2121use ndk:: native_window:: NativeWindow ;
2222
2323use crate :: error:: InternalResult ;
24- use crate :: input:: { Axis , KeyCharacterMap , KeyCharacterMapBinding } ;
24+ use crate :: input:: { Axis , KeyCharacterMap , KeyCharacterMapBinding , TextInputAction } ;
2525use crate :: jni_utils:: { self , CloneJavaVM } ;
2626use crate :: util:: { abort_on_panic, forward_stdio_to_logcat, log_panic, try_get_path_from_ptr} ;
2727use crate :: {
@@ -174,9 +174,6 @@ impl NativeAppGlue {
174174 } ;
175175 let out_ptr = & mut out_state as * mut TextInputState ;
176176
177- let app_ptr = self . as_ptr ( ) ;
178- ( * app_ptr) . textInputState = 0 ;
179-
180177 // NEON WARNING:
181178 //
182179 // It's not clearly documented but the GameActivity API over the
@@ -204,6 +201,14 @@ impl NativeAppGlue {
204201 }
205202 }
206203
204+ pub fn take_text_input_state ( & self ) -> TextInputState {
205+ unsafe {
206+ let app_ptr = self . as_ptr ( ) ;
207+ ( * app_ptr) . textInputState = 0 ;
208+ }
209+ self . text_input_state ( )
210+ }
211+
207212 // TODO: move into a trait
208213 pub fn set_text_input_state ( & self , state : TextInputState ) {
209214 unsafe {
@@ -247,6 +252,18 @@ impl NativeAppGlue {
247252 ffi:: GameActivity_setTextInputState ( activity, & ffi_state as * const _ ) ;
248253 }
249254 }
255+
256+ pub fn take_pending_editor_action ( & self ) -> Option < i32 > {
257+ unsafe {
258+ let app_ptr = self . as_ptr ( ) ;
259+ if ( * app_ptr) . pendingEditorAction {
260+ ( * app_ptr) . pendingEditorAction = false ;
261+ Some ( ( * app_ptr) . editorAction )
262+ } else {
263+ None
264+ }
265+ }
266+ }
250267}
251268
252269#[ derive( Debug ) ]
@@ -804,7 +821,8 @@ impl<'a> From<Arc<InputReceiver>> for InputIteratorInner<'a> {
804821 _receiver : receiver,
805822 buffered,
806823 native_app,
807- text_event_checked : false ,
824+ ime_text_input_state_checked : false ,
825+ ime_editor_action_checked : false ,
808826 }
809827 }
810828}
@@ -821,7 +839,8 @@ pub(crate) struct InputIteratorInner<'a> {
821839
822840 buffered : Option < BufferedEvents < ' a > > ,
823841 native_app : NativeAppGlue ,
824- text_event_checked : bool ,
842+ ime_text_input_state_checked : bool ,
843+ ime_editor_action_checked : bool ,
825844}
826845
827846impl InputIteratorInner < ' _ > {
@@ -841,8 +860,10 @@ impl InputIteratorInner<'_> {
841860 self . buffered = None ;
842861 }
843862
844- if !self . text_event_checked {
845- self . text_event_checked = true ;
863+ // We make sure any input state changes are sent before we check
864+ // for editor actions, so actions will apply to the latest state.
865+ if !self . ime_text_input_state_checked {
866+ self . ime_text_input_state_checked = true ;
846867 unsafe {
847868 let app_ptr = self . native_app . as_ptr ( ) ;
848869
@@ -854,12 +875,21 @@ impl InputIteratorInner<'_> {
854875 // the compiler isn't reordering code so this gets flagged
855876 // before the java main thread really updates the state.
856877 if ( * app_ptr) . textInputState != 0 {
857- let state = self . native_app . text_input_state ( ) ; // Will clear .textInputState
878+ let state = self . native_app . take_text_input_state ( ) ; // Will clear .textInputState
858879 let _ = callback ( & InputEvent :: TextEvent ( state) ) ;
859880 return true ;
860881 }
861882 }
862883 }
884+
885+ if !self . ime_editor_action_checked {
886+ self . ime_editor_action_checked = true ;
887+ if let Some ( action) = self . native_app . take_pending_editor_action ( ) {
888+ let _ = callback ( & InputEvent :: TextAction ( TextInputAction :: from ( action) ) ) ;
889+ return true ;
890+ }
891+ }
892+
863893 false
864894 }
865895}
0 commit comments