mirror of
https://git.ryujinx.app/kenji-nx/ryujinx.git
synced 2025-12-17 07:37:06 +00:00
Keyboard inputs fixed
This commit is contained in:
parent
be176fd367
commit
eee4a6272c
4 changed files with 95 additions and 37 deletions
|
|
@ -97,7 +97,8 @@ val jnaInstance: KenjinxNativeJna = Native.load(
|
||||||
|
|
||||||
object KenjinxNative : KenjinxNativeJna by jnaInstance {
|
object KenjinxNative : KenjinxNativeJna by jnaInstance {
|
||||||
|
|
||||||
fun loggingSetEnabled(logLevel: LogLevel, enabled: Boolean) = loggingSetEnabled(logLevel.ordinal, enabled)
|
fun loggingSetEnabled(logLevel: LogLevel, enabled: Boolean) =
|
||||||
|
loggingSetEnabled(logLevel.ordinal, enabled)
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun frameEnded() = MainActivity.frameEnded()
|
fun frameEnded() = MainActivity.frameEnded()
|
||||||
|
|
@ -116,6 +117,10 @@ object KenjinxNative : KenjinxNativeJna by jnaInstance {
|
||||||
progress
|
progress
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Variant A (Pointer → Strings via NativeHelpers).
|
||||||
|
* Used by older JNI/Interop paths.
|
||||||
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun updateUiHandler(
|
fun updateUiHandler(
|
||||||
newTitlePointer: Long,
|
newTitlePointer: Long,
|
||||||
|
|
@ -127,15 +132,54 @@ object KenjinxNative : KenjinxNativeJna by jnaInstance {
|
||||||
nMode: Int,
|
nMode: Int,
|
||||||
newSubtitlePointer: Long,
|
newSubtitlePointer: Long,
|
||||||
newInitialTextPointer: Long
|
newInitialTextPointer: Long
|
||||||
) = MainActivity.mainViewModel?.activity?.uiHandler?.update(
|
) {
|
||||||
newTitle = NativeHelpers.instance.getStringJava(newTitlePointer),
|
val title = NativeHelpers.instance.getStringJava(newTitlePointer)
|
||||||
newMessage = NativeHelpers.instance.getStringJava(newMessagePointer),
|
val message = NativeHelpers.instance.getStringJava(newMessagePointer)
|
||||||
newWatermark = NativeHelpers.instance.getStringJava(newWatermarkPointer),
|
val watermark = NativeHelpers.instance.getStringJava(newWatermarkPointer)
|
||||||
newType,
|
val subtitle = NativeHelpers.instance.getStringJava(newSubtitlePointer)
|
||||||
min,
|
val initialText = NativeHelpers.instance.getStringJava(newInitialTextPointer)
|
||||||
max,
|
val mode = KeyboardMode.entries.getOrNull(nMode) ?: KeyboardMode.Default
|
||||||
newMode = KeyboardMode.entries[nMode],
|
|
||||||
newSubtitle = NativeHelpers.instance.getStringJava(newSubtitlePointer),
|
MainActivity.mainViewModel?.activity?.uiHandler?.update(
|
||||||
NativeHelpers.instance.getStringJava(newInitialTextPointer)
|
newTitle = title,
|
||||||
|
newMessage = message,
|
||||||
|
newWatermark = watermark,
|
||||||
|
newType = newType,
|
||||||
|
min = min,
|
||||||
|
max = max,
|
||||||
|
newMode = mode,
|
||||||
|
newSubtitle = subtitle,
|
||||||
|
newInitialText = initialText
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Variant B (strings directly). Used by newer JNI/Interop paths.
|
||||||
|
* Signature exactly matches the C# call in AndroidUIHandler.cs / Interop.UpdateUiHandler(...).
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun uiHandlerUpdate(
|
||||||
|
title: String,
|
||||||
|
message: String,
|
||||||
|
watermark: String,
|
||||||
|
type: Int,
|
||||||
|
min: Int,
|
||||||
|
max: Int,
|
||||||
|
nMode: Int,
|
||||||
|
subtitle: String,
|
||||||
|
initialText: String
|
||||||
|
) {
|
||||||
|
val mode = KeyboardMode.entries.getOrNull(nMode) ?: KeyboardMode.Default
|
||||||
|
MainActivity.mainViewModel?.activity?.uiHandler?.update(
|
||||||
|
newTitle = title,
|
||||||
|
newMessage = message,
|
||||||
|
newWatermark = watermark,
|
||||||
|
newType = type,
|
||||||
|
min = min,
|
||||||
|
max = max,
|
||||||
|
newMode = mode,
|
||||||
|
newSubtitle = subtitle,
|
||||||
|
newInitialText = initialText
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ import org.kenjinx.android.viewmodels.GameModel
|
||||||
import org.kenjinx.android.views.MainView
|
import org.kenjinx.android.views.MainView
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
|
|
||||||
|
|
||||||
class MainActivity : BaseActivity() {
|
class MainActivity : BaseActivity() {
|
||||||
private var physicalControllerManager: PhysicalControllerManager =
|
private var physicalControllerManager: PhysicalControllerManager =
|
||||||
PhysicalControllerManager(this)
|
PhysicalControllerManager(this)
|
||||||
|
|
@ -123,8 +122,7 @@ class MainActivity : BaseActivity() {
|
||||||
motionSensorManager = MotionSensorManager(this)
|
motionSensorManager = MotionSensorManager(this)
|
||||||
Thread.setDefaultUncaughtExceptionHandler(crashHandler)
|
Thread.setDefaultUncaughtExceptionHandler(crashHandler)
|
||||||
|
|
||||||
if (
|
if (!Environment.isExternalStorageManager()
|
||||||
!Environment.isExternalStorageManager()
|
|
||||||
) {
|
) {
|
||||||
storageHelper?.storage?.requestFullStorageAccess()
|
storageHelper?.storage?.requestFullStorageAccess()
|
||||||
}
|
}
|
||||||
|
|
@ -143,6 +141,9 @@ class MainActivity : BaseActivity() {
|
||||||
controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// >>> Important: Initialize UI handler (for software keyboard/dialog)
|
||||||
|
uiHandler = UiHandler()
|
||||||
|
|
||||||
mainViewModel = MainViewModel(this)
|
mainViewModel = MainViewModel(this)
|
||||||
mainViewModel!!.physicalControllerManager = physicalControllerManager
|
mainViewModel!!.physicalControllerManager = physicalControllerManager
|
||||||
mainViewModel!!.motionSensorManager = motionSensorManager
|
mainViewModel!!.motionSensorManager = motionSensorManager
|
||||||
|
|
@ -152,7 +153,6 @@ class MainActivity : BaseActivity() {
|
||||||
mainViewModel?.apply {
|
mainViewModel?.apply {
|
||||||
setContent {
|
setContent {
|
||||||
KenjinxAndroidTheme {
|
KenjinxAndroidTheme {
|
||||||
// A surface container using the 'background' color from the theme
|
|
||||||
Surface(
|
Surface(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
color = MaterialTheme.colorScheme.background
|
color = MaterialTheme.colorScheme.background
|
||||||
|
|
@ -219,7 +219,7 @@ class MainActivity : BaseActivity() {
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
super.onPause()
|
super.onPause()
|
||||||
isActive = true
|
isActive = false
|
||||||
|
|
||||||
if (isGameRunning) {
|
if (isGameRunning) {
|
||||||
mainViewModel?.performanceManager?.setTurboMode(false)
|
mainViewModel?.performanceManager?.setTurboMode(false)
|
||||||
|
|
@ -232,7 +232,7 @@ class MainActivity : BaseActivity() {
|
||||||
when (storedIntent.action) {
|
when (storedIntent.action) {
|
||||||
Intent.ACTION_VIEW, "org.kenjinx.android.LAUNCH_GAME" -> {
|
Intent.ACTION_VIEW, "org.kenjinx.android.LAUNCH_GAME" -> {
|
||||||
val bootPath = storedIntent.getStringExtra("bootPath")
|
val bootPath = storedIntent.getStringExtra("bootPath")
|
||||||
val forceNceAndPptc = storedIntent.getBooleanExtra("forceNceAndPptc",false)
|
val forceNceAndPptc = storedIntent.getBooleanExtra("forceNceAndPptc", false)
|
||||||
|
|
||||||
if (bootPath != null) {
|
if (bootPath != null) {
|
||||||
val uri = bootPath.toUri()
|
val uri = bootPath.toUri()
|
||||||
|
|
@ -260,7 +260,6 @@ class MainActivity : BaseActivity() {
|
||||||
|
|
||||||
// Clean up resources if needed
|
// Clean up resources if needed
|
||||||
mainViewModel?.let {
|
mainViewModel?.let {
|
||||||
// Perform any critical cleanup
|
|
||||||
it.performanceManager?.setTurboMode(false)
|
it.performanceManager?.setTurboMode(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,12 @@ import androidx.compose.material3.TextField
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.focus.FocusRequester
|
||||||
|
import androidx.compose.ui.focus.focusRequester
|
||||||
|
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
||||||
import androidx.compose.ui.text.input.ImeAction
|
import androidx.compose.ui.text.input.ImeAction
|
||||||
import androidx.compose.ui.text.input.KeyboardType
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
|
@ -27,6 +31,7 @@ import androidx.compose.ui.window.DialogProperties
|
||||||
import com.halilibo.richtext.markdown.Markdown
|
import com.halilibo.richtext.markdown.Markdown
|
||||||
import com.halilibo.richtext.ui.material3.RichText
|
import com.halilibo.richtext.ui.material3.RichText
|
||||||
import org.kenjinx.android.widgets.SimpleAlertDialog
|
import org.kenjinx.android.widgets.SimpleAlertDialog
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
|
||||||
enum class KeyboardMode {
|
enum class KeyboardMode {
|
||||||
Default, Numeric, ASCII, FullLatin, Alphabet, SimplifiedChinese, TraditionalChinese, Korean, LanguageSet2, LanguageSet2Latin
|
Default, Numeric, ASCII, FullLatin, Alphabet, SimplifiedChinese, TraditionalChinese, Korean, LanguageSet2, LanguageSet2Latin
|
||||||
|
|
@ -46,6 +51,7 @@ class UiHandler {
|
||||||
var message: String = ""
|
var message: String = ""
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
// 2.0.3 compatible: no parameters
|
||||||
KenjinxNative.uiHandlerSetup()
|
KenjinxNative.uiHandlerSetup()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -77,15 +83,21 @@ class UiHandler {
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun Compose() {
|
fun Compose() {
|
||||||
val showMessageListener = remember {
|
val showMessageListener = remember { showMessage }
|
||||||
showMessage
|
val inputListener = remember { inputText }
|
||||||
}
|
val validation = remember { mutableStateOf("") }
|
||||||
|
|
||||||
val inputListener = remember {
|
// Focus & keyboard control so the popup can be typed immediately like in 2.0.3
|
||||||
inputText
|
val focusRequester = remember { FocusRequester() }
|
||||||
|
val keyboard = LocalSoftwareKeyboardController.current
|
||||||
|
|
||||||
|
LaunchedEffect(showMessageListener.value, type) {
|
||||||
|
if (showMessageListener.value && type == 2) {
|
||||||
|
// small delay until the dialog is mounted
|
||||||
|
delay(100)
|
||||||
|
focusRequester.requestFocus()
|
||||||
|
keyboard?.show()
|
||||||
}
|
}
|
||||||
val validation = remember {
|
|
||||||
mutableStateOf("")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun validate(): Boolean {
|
fun validate(): Boolean {
|
||||||
|
|
@ -94,7 +106,6 @@ class UiHandler {
|
||||||
} else {
|
} else {
|
||||||
return inputText.value.length < minLength || inputText.value.length > maxLength
|
return inputText.value.length < minLength || inputText.value.length > maxLength
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -103,9 +114,7 @@ class UiHandler {
|
||||||
KeyboardMode.Default -> KeyboardType.Text
|
KeyboardMode.Default -> KeyboardType.Text
|
||||||
KeyboardMode.Numeric -> KeyboardType.Decimal
|
KeyboardMode.Numeric -> KeyboardType.Decimal
|
||||||
KeyboardMode.ASCII -> KeyboardType.Ascii
|
KeyboardMode.ASCII -> KeyboardType.Ascii
|
||||||
else -> {
|
else -> KeyboardType.Text
|
||||||
KeyboardType.Text
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -160,10 +169,9 @@ class UiHandler {
|
||||||
onValueChange = { inputListener.value = it },
|
onValueChange = { inputListener.value = it },
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(4.dp),
|
.padding(4.dp)
|
||||||
label = {
|
.focusRequester(focusRequester),
|
||||||
Text(text = watermark)
|
label = { Text(text = watermark) },
|
||||||
},
|
|
||||||
keyboardOptions = KeyboardOptions(keyboardType = getInputType()),
|
keyboardOptions = KeyboardOptions(keyboardType = getInputType()),
|
||||||
isError = validate()
|
isError = validate()
|
||||||
)
|
)
|
||||||
|
|
@ -173,7 +181,8 @@ class UiHandler {
|
||||||
onValueChange = { inputListener.value = it },
|
onValueChange = { inputListener.value = it },
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(4.dp),
|
.padding(4.dp)
|
||||||
|
.focusRequester(focusRequester),
|
||||||
keyboardOptions = KeyboardOptions(
|
keyboardOptions = KeyboardOptions(
|
||||||
keyboardType = getInputType(),
|
keyboardType = getInputType(),
|
||||||
imeAction = ImeAction.Done
|
imeAction = ImeAction.Done
|
||||||
|
|
@ -211,4 +220,3 @@ class UiHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -250,6 +250,13 @@ class GameViews {
|
||||||
mutableStateOf(false)
|
mutableStateOf(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NEW: If the software keyboard is open, catch Back and close ONLY the dialog.
|
||||||
|
val uiHandler = mainViewModel.activity.uiHandler
|
||||||
|
BackHandler(enabled = uiHandler.showMessage.value) {
|
||||||
|
KenjinxNative.uiHandlerSetResponse(false, "")
|
||||||
|
uiHandler.showMessage.value = false
|
||||||
|
}
|
||||||
|
|
||||||
BackHandler {
|
BackHandler {
|
||||||
showBackNotice.value = true
|
showBackNotice.value = true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue