@@ -8,8 +8,11 @@ import android.graphics.Color
88import android.graphics.Typeface
99import android.os.Build
1010import android.util.TypedValue
11+ import android.view.KeyEvent
1112import android.view.View
1213import android.view.Window
14+ import android.view.inputmethod.EditorInfo
15+ import android.widget.EditText
1316import androidx.activity.compose.BackHandler
1417import androidx.compose.animation.animateColorAsState
1518import androidx.compose.foundation.Image
@@ -31,6 +34,8 @@ import androidx.compose.foundation.layout.size
3134import androidx.compose.foundation.layout.width
3235import androidx.compose.foundation.lazy.LazyColumn
3336import androidx.compose.foundation.lazy.items
37+ import androidx.compose.foundation.pager.HorizontalPager
38+ import androidx.compose.foundation.pager.rememberPagerState
3439import androidx.compose.foundation.shape.RoundedCornerShape
3540import androidx.compose.material.icons.Icons
3641import androidx.compose.material.icons.filled.Add
@@ -63,6 +68,7 @@ import androidx.compose.runtime.getValue
6368import androidx.compose.runtime.mutableStateOf
6469import androidx.compose.runtime.remember
6570import androidx.compose.runtime.rememberCoroutineScope
71+ import androidx.compose.runtime.saveable.rememberSaveable
6672import androidx.compose.runtime.setValue
6773import androidx.compose.ui.Alignment
6874import androidx.compose.ui.Modifier
@@ -75,6 +81,7 @@ import androidx.compose.ui.graphics.BlendMode
7581import androidx.compose.ui.graphics.ImageBitmap
7682import androidx.compose.ui.graphics.asImageBitmap
7783import androidx.compose.ui.graphics.drawscope.clipRect
84+ import androidx.compose.ui.graphics.toArgb
7885import androidx.compose.ui.layout.ContentScale
7986import androidx.compose.ui.platform.ComposeView
8087import androidx.compose.ui.platform.LocalConfiguration
@@ -94,6 +101,7 @@ import androidx.compose.ui.zIndex
94101import androidx.core.view.WindowCompat
95102import androidx.core.view.WindowInsetsCompat
96103import androidx.core.view.WindowInsetsControllerCompat
104+ import androidx.core.widget.doOnTextChanged
97105import androidx.navigation.NavController
98106import androidx.palette.graphics.Palette
99107import com.google.accompanist.systemuicontroller.rememberSystemUiController
@@ -538,56 +546,105 @@ fun TerminalScreen(
538546 )
539547
540548 if (showVirtualKeys.value){
541- AndroidView (update = {
542- it.apply {
543- virtualKeysViewClient =
544- terminalView.get()?.mTermSession?.let {
545- VirtualKeysListener (
546- it
547- )
548- }
549-
550-
551- buttonTextColor = getViewColor()
552-
553-
554- reload(
555- VirtualKeysInfo (
556- VIRTUAL_KEYS ,
557- " " ,
558- VirtualKeysConstants .CONTROL_CHARS_ALIASES
549+ val pagerState = rememberPagerState(pageCount = { 2 })
550+ val onSurfaceColor = MaterialTheme .colorScheme.onSurface.toArgb()
551+ HorizontalPager (
552+ state = pagerState,
553+ modifier = Modifier
554+ .fillMaxWidth()
555+ .height(75 .dp)
556+ ) { page ->
557+ when (page) {
558+ 0 -> {
559+ terminalView.get()?.requestFocus()
560+ // terminalView.get()?.requestFocusFromTouch()
561+ AndroidView (
562+ factory = { context ->
563+ VirtualKeysView (context, null ).apply {
564+ virtualKeysView = WeakReference (this )
565+ virtualKeysViewClient =
566+ terminalView.get()?.mTermSession?.let {
567+ VirtualKeysListener (
568+ it
569+ )
570+ }
571+
572+ buttonTextColor = onSurfaceColor!!
573+
574+ reload(
575+ VirtualKeysInfo (
576+ VIRTUAL_KEYS ,
577+ " " ,
578+ VirtualKeysConstants .CONTROL_CHARS_ALIASES
579+ )
580+ )
581+ }
582+ },
583+ modifier = Modifier
584+ .fillMaxWidth()
585+ .height(75 .dp)
559586 )
560- )
561- }
562- },
563- factory = { context ->
564- VirtualKeysView (context, null ).apply {
565- virtualKeysView = WeakReference (this )
566-
567- virtualKeysViewClient =
568- terminalView.get()?.mTermSession?.let {
569- VirtualKeysListener (
570- it
571- )
572- }
573-
574-
575- buttonTextColor = getViewColor()
576-
587+ }
577588
578- reload(
579- VirtualKeysInfo (
580- VIRTUAL_KEYS ,
581- " " ,
582- VirtualKeysConstants .CONTROL_CHARS_ALIASES
583- )
589+ 1 -> {
590+ var text by rememberSaveable { mutableStateOf(" " ) }
591+
592+ AndroidView (
593+ modifier = Modifier
594+ .fillMaxWidth()
595+ .height(75 .dp),
596+ factory = { ctx ->
597+ EditText (ctx).apply {
598+ maxLines = 1
599+ isSingleLine = true
600+ imeOptions = EditorInfo .IME_ACTION_DONE
601+
602+ // Listen for text changes to update Compose state
603+ doOnTextChanged { textInput, _, _, _ ->
604+ text = textInput.toString()
605+ }
606+
607+ setOnEditorActionListener { v, actionId, event ->
608+ if (actionId == EditorInfo .IME_ACTION_DONE ) {
609+ if (text.isEmpty()) {
610+ // Dispatch enter key events if text is empty
611+ val eventDown = KeyEvent (
612+ KeyEvent .ACTION_DOWN ,
613+ KeyEvent .KEYCODE_ENTER
614+ )
615+ val eventUp = KeyEvent (
616+ KeyEvent .ACTION_UP ,
617+ KeyEvent .KEYCODE_ENTER
618+ )
619+ terminalView.get()
620+ ?.dispatchKeyEvent(eventDown)
621+ terminalView.get()
622+ ?.dispatchKeyEvent(eventUp)
623+ } else {
624+ terminalView.get()?.currentSession?.write(
625+ text
626+ )
627+ setText(" " )
628+ }
629+ true
630+ } else {
631+ false
632+ }
633+ }
634+ }
635+ },
636+ update = { editText ->
637+ // Keep EditText's text in sync with Compose state, avoid infinite loop by only updating if different
638+ if (editText.text.toString() != text) {
639+ editText.setText(text)
640+ editText.setSelection(text.length)
641+ }
642+ }
584643 )
585644 }
586- },
587- modifier = Modifier
588- .fillMaxWidth()
589- .height(75 .dp)
590- )
645+ }
646+
647+ }
591648 }else {
592649 virtualKeysView = WeakReference (null )
593650 }
0 commit comments