aboutsummaryrefslogtreecommitdiff
path: root/src/android
diff options
context:
space:
mode:
authorwildcard <nubieluv@gmail.com>2026-04-23 03:43:54 +0200
committercrueter <crueter@eden-emu.dev>2026-04-23 03:43:54 +0200
commit838cc926f6c87a25cccab2dcd2e73f5b5baa8440 (patch)
treeeb72a92206c0fbc4b3a05ba2dcd49aae84be5943 /src/android
parent860acb4faf0b453912c451238b44f77e6a7a7fdf (diff)
keyboard fixes (#3865)
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3865 Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Diffstat (limited to 'src/android')
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/applets/keyboard/SoftwareKeyboard.kt6
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt84
2 files changed, 90 insertions, 0 deletions
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/applets/keyboard/SoftwareKeyboard.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/applets/keyboard/SoftwareKeyboard.kt
index e058067c97..26e787f377 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/applets/keyboard/SoftwareKeyboard.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/applets/keyboard/SoftwareKeyboard.kt
@@ -1,3 +1,7 @@
+
+// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -33,8 +37,10 @@ object SoftwareKeyboard {
val emulationActivity = NativeLibrary.sEmulationActivity.get()
val overlayView = emulationActivity!!.findViewById<View>(R.id.surface_input_overlay)
+ overlayView.requestFocus()
val im =
overlayView.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
+ im.restartInput(overlayView)
im.showSoftInput(overlayView, InputMethodManager.SHOW_FORCED)
// There isn't a good way to know that the IMM is dismissed, so poll every 500ms to submit inline keyboard result.
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt
index d3b5d86174..7ff9c78923 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt
@@ -17,16 +17,23 @@ import android.graphics.drawable.VectorDrawable
import android.os.Build
import android.os.Handler
import android.os.Looper
+import android.text.Editable
+import android.text.InputType
import android.util.AttributeSet
import android.view.HapticFeedbackConstants
+import android.view.KeyEvent
import android.view.MotionEvent
import android.view.View
import android.view.View.OnTouchListener
import android.view.WindowInsets
+import android.view.inputmethod.BaseInputConnection
+import android.view.inputmethod.EditorInfo
+import android.view.inputmethod.InputConnection
import androidx.core.content.ContextCompat
import androidx.window.layout.WindowMetricsCalculator
import kotlin.math.max
import kotlin.math.min
+import org.yuzu.yuzu_emu.NativeLibrary
import org.yuzu.yuzu_emu.features.input.NativeInput
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.features.input.model.NativeAnalog
@@ -49,6 +56,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
private val overlayButtons: MutableSet<InputOverlayDrawableButton> = HashSet()
private val overlayDpads: MutableSet<InputOverlayDrawableDpad> = HashSet()
private val overlayJoysticks: MutableSet<InputOverlayDrawableJoystick> = HashSet()
+ private val imeEditable = Editable.Factory.getInstance().newEditable("")
private var inEditMode = false
private var gamelessMode = false
@@ -75,6 +83,63 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
// External listener for EmulationFragment joypad overlay auto-hide
var touchEventListener: ((MotionEvent) -> Unit)? = null
+ override fun onCheckIsTextEditor(): Boolean = true
+
+ override fun onCreateInputConnection(outAttrs: EditorInfo): InputConnection {
+ imeEditable.clear()
+ outAttrs.inputType =
+ InputType.TYPE_CLASS_TEXT or
+ InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS or
+ InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
+ outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI or EditorInfo.IME_ACTION_DONE
+ outAttrs.initialSelStart = 0
+ outAttrs.initialSelEnd = 0
+
+ return object : BaseInputConnection(this, true) {
+ override fun getEditable(): Editable = imeEditable
+
+ override fun commitText(text: CharSequence?, newCursorPosition: Int): Boolean {
+ if (!text.isNullOrEmpty()) {
+ forwardCommittedText(text)
+ }
+ return super.commitText(text, newCursorPosition)
+ }
+
+ override fun deleteSurroundingText(beforeLength: Int, afterLength: Int): Boolean {
+ repeat(beforeLength.coerceAtLeast(0)) {
+ NativeLibrary.submitInlineKeyboardInput(KeyEvent.KEYCODE_DEL)
+ }
+ return super.deleteSurroundingText(beforeLength, afterLength)
+ }
+
+ override fun sendKeyEvent(event: KeyEvent): Boolean {
+ if (event.action != KeyEvent.ACTION_DOWN) {
+ return true
+ }
+
+ when (event.keyCode) {
+ KeyEvent.KEYCODE_BACK,
+ KeyEvent.KEYCODE_DEL,
+ KeyEvent.KEYCODE_ENTER -> {
+ NativeLibrary.submitInlineKeyboardInput(event.keyCode)
+ }
+ else -> {
+ val textChar = event.unicodeChar
+ if (textChar != 0) {
+ NativeLibrary.submitInlineKeyboardText(textChar.toChar().toString())
+ }
+ }
+ }
+ return true
+ }
+
+ override fun performEditorAction(actionCode: Int): Boolean {
+ NativeLibrary.submitInlineKeyboardInput(KeyEvent.KEYCODE_ENTER)
+ return true
+ }
+ }
+ }
+
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
super.onLayout(changed, left, top, right, bottom)
@@ -119,6 +184,25 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
}
}
+ private fun forwardCommittedText(text: CharSequence) {
+ val builder = StringBuilder()
+ text.forEach { character ->
+ when (character) {
+ '\n' -> {
+ if (builder.isNotEmpty()) {
+ NativeLibrary.submitInlineKeyboardText(builder.toString())
+ builder.clear()
+ }
+ NativeLibrary.submitInlineKeyboardInput(KeyEvent.KEYCODE_ENTER)
+ }
+ else -> builder.append(character)
+ }
+ }
+ if (builder.isNotEmpty()) {
+ NativeLibrary.submitInlineKeyboardText(builder.toString())
+ }
+ }
+
private fun drawGrid(canvas: Canvas) {
val gridSize = IntSetting.OVERLAY_GRID_SIZE.getInt()
val width = canvas.width