mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-05-17 21:06:59 +02:00
keyboard fixes (#3865)
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3865 Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
This commit is contained in:
parent
860acb4faf
commit
838cc926f6
3 changed files with 93 additions and 0 deletions
|
|
@ -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-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
|
@ -33,8 +37,10 @@ object SoftwareKeyboard {
|
||||||
val emulationActivity = NativeLibrary.sEmulationActivity.get()
|
val emulationActivity = NativeLibrary.sEmulationActivity.get()
|
||||||
|
|
||||||
val overlayView = emulationActivity!!.findViewById<View>(R.id.surface_input_overlay)
|
val overlayView = emulationActivity!!.findViewById<View>(R.id.surface_input_overlay)
|
||||||
|
overlayView.requestFocus()
|
||||||
val im =
|
val im =
|
||||||
overlayView.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
overlayView.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||||
|
im.restartInput(overlayView)
|
||||||
im.showSoftInput(overlayView, InputMethodManager.SHOW_FORCED)
|
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.
|
// There isn't a good way to know that the IMM is dismissed, so poll every 500ms to submit inline keyboard result.
|
||||||
|
|
|
||||||
|
|
@ -17,16 +17,23 @@ import android.graphics.drawable.VectorDrawable
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
|
import android.text.Editable
|
||||||
|
import android.text.InputType
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.HapticFeedbackConstants
|
import android.view.HapticFeedbackConstants
|
||||||
|
import android.view.KeyEvent
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.View.OnTouchListener
|
import android.view.View.OnTouchListener
|
||||||
import android.view.WindowInsets
|
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.core.content.ContextCompat
|
||||||
import androidx.window.layout.WindowMetricsCalculator
|
import androidx.window.layout.WindowMetricsCalculator
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
import org.yuzu.yuzu_emu.NativeLibrary
|
||||||
import org.yuzu.yuzu_emu.features.input.NativeInput
|
import org.yuzu.yuzu_emu.features.input.NativeInput
|
||||||
import org.yuzu.yuzu_emu.R
|
import org.yuzu.yuzu_emu.R
|
||||||
import org.yuzu.yuzu_emu.features.input.model.NativeAnalog
|
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 overlayButtons: MutableSet<InputOverlayDrawableButton> = HashSet()
|
||||||
private val overlayDpads: MutableSet<InputOverlayDrawableDpad> = HashSet()
|
private val overlayDpads: MutableSet<InputOverlayDrawableDpad> = HashSet()
|
||||||
private val overlayJoysticks: MutableSet<InputOverlayDrawableJoystick> = HashSet()
|
private val overlayJoysticks: MutableSet<InputOverlayDrawableJoystick> = HashSet()
|
||||||
|
private val imeEditable = Editable.Factory.getInstance().newEditable("")
|
||||||
|
|
||||||
private var inEditMode = false
|
private var inEditMode = false
|
||||||
private var gamelessMode = false
|
private var gamelessMode = false
|
||||||
|
|
@ -75,6 +83,63 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||||
// External listener for EmulationFragment joypad overlay auto-hide
|
// External listener for EmulationFragment joypad overlay auto-hide
|
||||||
var touchEventListener: ((MotionEvent) -> Unit)? = null
|
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) {
|
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
|
||||||
super.onLayout(changed, left, top, right, bottom)
|
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) {
|
private fun drawGrid(canvas: Canvas) {
|
||||||
val gridSize = IntSetting.OVERLAY_GRID_SIZE.getInt()
|
val gridSize = IntSetting.OVERLAY_GRID_SIZE.getInt()
|
||||||
val width = canvas.width
|
val width = canvas.width
|
||||||
|
|
|
||||||
|
|
@ -243,6 +243,9 @@ void AndroidKeyboard::SubmitInlineKeyboardInput(int key_code) {
|
||||||
static_cast<s32>(m_current_text.size()));
|
static_cast<s32>(m_current_text.size()));
|
||||||
break;
|
break;
|
||||||
case KEYCODE_DEL:
|
case KEYCODE_DEL:
|
||||||
|
if (m_current_text.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
m_current_text.pop_back();
|
m_current_text.pop_back();
|
||||||
submit_inline_callback(Service::AM::Frontend::SwkbdReplyType::ChangedString, m_current_text,
|
submit_inline_callback(Service::AM::Frontend::SwkbdReplyType::ChangedString, m_current_text,
|
||||||
static_cast<int>(m_current_text.size()));
|
static_cast<int>(m_current_text.size()));
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue