@@ -18,15 +18,23 @@ import android.provider.Settings
1818import android.util.Log
1919import android.view.*
2020import android.widget.Toast
21+ import android.widget.EditText
22+ import android.text.TextWatcher
23+ import android.text.Editable
24+ import android.view.inputmethod.EditorInfo
25+ import android.text.InputType
26+ import android.view.inputmethod.InputMethodManager
2127import androidx.annotation.RequiresApi
2228import androidx.core.app.ActivityCompat
2329import androidx.core.content.ContextCompat
2430import org.koreader.launcher.device.Device
2531import org.koreader.launcher.dialog.LightDialog
2632import org.koreader.launcher.extensions.*
2733import java.io.File
34+ import java.io.FileWriter
2835import java.util.Locale
2936import java.util.concurrent.CountDownLatch
37+ import java.util.concurrent.ConcurrentLinkedQueue
3038
3139class MainActivity : NativeActivity (), LuaInterface,
3240 ActivityCompat .OnRequestPermissionsResultCallback {
@@ -67,6 +75,88 @@ class MainActivity : NativeActivity(), LuaInterface,
6775 // Hardware orientation for this device (usually match android boot logo)
6876 private var screenIsLandscape: Boolean = false
6977
78+ /* ---------------------------------------------------------------
79+ * IME bridge state *
80+ *--------------------------------------------------------------*/
81+ private var imeEditText: EditText ? = null
82+ private val imeQueue = ConcurrentLinkedQueue <String >()
83+
84+ private fun ensureImeEditText (): EditText {
85+ var et = imeEditText
86+ if (et == null ) {
87+ et = EditText (this )
88+ et.isSingleLine = false
89+ et.imeOptions = EditorInfo .IME_FLAG_NO_EXTRACT_UI or EditorInfo .IME_ACTION_NONE
90+ et.inputType = InputType .TYPE_CLASS_TEXT or InputType .TYPE_TEXT_FLAG_MULTI_LINE
91+ et.isFocusable = true
92+ et.isFocusableInTouchMode = true
93+ et.visibility = View .VISIBLE
94+ et.alpha = 0f
95+ et.addTextChangedListener(object : TextWatcher {
96+ override fun beforeTextChanged (s : CharSequence? , start : Int , count : Int , after : Int ) {}
97+ override fun onTextChanged (s : CharSequence? , start : Int , before : Int , count : Int ) {
98+ Log .i(tag, " text changed!" );
99+ if (s == null ) return
100+ if (count > 0 ) {
101+ val end = start + count
102+ if (start >= 0 && end <= s.length) {
103+ val inserted = s.subSequence(start, end).toString()
104+ Log .i(tag, " in if" );
105+ if (inserted.isNotEmpty()) {
106+ Log .i(tag, " got text $inserted " )
107+ imeQueue.add(inserted)
108+ // 120 == AEVENT_TEXT_INPUT
109+ event.write(120 )
110+ et.text?.clear()
111+ }
112+ }
113+ }
114+ }
115+ override fun afterTextChanged (s : Editable ? ) {}
116+ })
117+
118+ // Attach to window without disturbing native content
119+ val lp = ViewGroup .LayoutParams (1 , 1 )
120+ addContentView(et, lp)
121+ imeEditText = et
122+ }
123+ return et
124+ }
125+
126+ @Suppress(" unused" )
127+ override fun startTextInput () {
128+ runOnUiThread {
129+ val et = ensureImeEditText()
130+ if (et.visibility != View .VISIBLE ) et.visibility = View .VISIBLE
131+ et.alpha = 0f
132+ et.post {
133+ if (! et.isFocused) et.requestFocus()
134+ val imm = getSystemService(Context .INPUT_METHOD_SERVICE ) as InputMethodManager
135+ imm.showSoftInput(et, InputMethodManager .SHOW_IMPLICIT )
136+ }
137+ }
138+ }
139+
140+ @Suppress(" unused" )
141+ override fun stopTextInput () {
142+ runOnUiThread {
143+ imeEditText?.let { et ->
144+ val imm = getSystemService(Context .INPUT_METHOD_SERVICE ) as InputMethodManager
145+ imm.hideSoftInputFromWindow(et.windowToken, 0 )
146+ et.clearFocus()
147+ et.alpha = 0f
148+ et.visibility = View .VISIBLE
149+ et.text?.clear()
150+ }
151+ }
152+ }
153+
154+ @Suppress(" unused" )
155+ override fun dequeueCommittedText (): String? {
156+ Log .i(tag, " dequeueCommittedText" )
157+ return imeQueue.poll()
158+ }
159+
70160 companion object {
71161 private const val TAG_SURFACE = " Surface"
72162 private const val MANDATORY_PERMISSIONS_ID = 1
@@ -116,6 +206,9 @@ class MainActivity : NativeActivity(), LuaInterface,
116206
117207 // Window background must be black for vertical and horizontal lines to be visible
118208 window.setBackgroundDrawableResource(android.R .color.black)
209+ // Allow IME to interact with this window and resize content with soft keyboard
210+ window.clearFlags(WindowManager .LayoutParams .FLAG_ALT_FOCUSABLE_IM )
211+ window.setSoftInputMode(WindowManager .LayoutParams .SOFT_INPUT_ADJUST_RESIZE )
119212
120213 val surfaceKind: String = if (device.needsView) {
121214 view = NativeSurfaceView (this )
0 commit comments