diff options
Diffstat (limited to 'src/android/app/src/main/java/org/yuzu/yuzu_emu/applets/keyboard/SoftwareKeyboard.kt')
-rw-r--r-- | src/android/app/src/main/java/org/yuzu/yuzu_emu/applets/keyboard/SoftwareKeyboard.kt | 121 |
1 files changed, 121 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 new file mode 100644 index 000000000..82a6712b6 --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/applets/keyboard/SoftwareKeyboard.kt @@ -0,0 +1,121 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +package org.yuzu.yuzu_emu.applets.keyboard + +import android.content.Context +import android.os.Handler +import android.os.Looper +import android.view.KeyEvent +import android.view.View +import android.view.WindowInsets +import android.view.inputmethod.InputMethodManager +import androidx.annotation.Keep +import androidx.core.view.ViewCompat +import org.yuzu.yuzu_emu.NativeLibrary +import org.yuzu.yuzu_emu.R +import org.yuzu.yuzu_emu.applets.keyboard.ui.KeyboardDialogFragment +import java.io.Serializable + +@Keep +object SoftwareKeyboard { + lateinit var data: KeyboardData + val dataLock = Object() + + private fun executeNormalImpl(config: KeyboardConfig) { + val emulationActivity = NativeLibrary.sEmulationActivity.get() + data = KeyboardData(SwkbdResult.Cancel.ordinal, "") + val fragment = KeyboardDialogFragment.newInstance(config) + fragment.show(emulationActivity!!.supportFragmentManager, KeyboardDialogFragment.TAG) + } + + private fun executeInlineImpl(config: KeyboardConfig) { + val emulationActivity = NativeLibrary.sEmulationActivity.get() + + val overlayView = emulationActivity!!.findViewById<View>(R.id.surface_input_overlay) + val im = + overlayView.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + 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. + val handler = Handler(Looper.myLooper()!!) + val delayMs = 500 + handler.postDelayed(object : Runnable { + override fun run() { + val insets = ViewCompat.getRootWindowInsets(overlayView) + val isKeyboardVisible = insets!!.isVisible(WindowInsets.Type.ime()) + if (isKeyboardVisible) { + handler.postDelayed(this, delayMs.toLong()) + return + } + + // No longer visible, submit the result. + NativeLibrary.submitInlineKeyboardInput(KeyEvent.KEYCODE_ENTER) + } + }, delayMs.toLong()) + } + + @JvmStatic + fun executeNormal(config: KeyboardConfig): KeyboardData { + NativeLibrary.sEmulationActivity.get()!!.runOnUiThread { executeNormalImpl(config) } + synchronized(dataLock) { + dataLock.wait() + } + return data + } + + @JvmStatic + fun executeInline(config: KeyboardConfig) { + NativeLibrary.sEmulationActivity.get()!!.runOnUiThread { executeInlineImpl(config) } + } + + // Corresponds to Service::AM::Applets::SwkbdType + enum class SwkbdType { + Normal, + NumberPad, + Qwerty, + Unknown3, + Latin, + SimplifiedChinese, + TraditionalChinese, + Korean + } + + // Corresponds to Service::AM::Applets::SwkbdPasswordMode + enum class SwkbdPasswordMode { + Disabled, + Enabled + } + + // Corresponds to Service::AM::Applets::SwkbdResult + enum class SwkbdResult { + Ok, + Cancel + } + + @Keep + data class KeyboardConfig( + var ok_text: String? = null, + var header_text: String? = null, + var sub_text: String? = null, + var guide_text: String? = null, + var initial_text: String? = null, + var left_optional_symbol_key: Short = 0, + var right_optional_symbol_key: Short = 0, + var max_text_length: Int = 0, + var min_text_length: Int = 0, + var initial_cursor_position: Int = 0, + var type: Int = 0, + var password_mode: Int = 0, + var text_draw_type: Int = 0, + var key_disable_flags: Int = 0, + var use_blur_background: Boolean = false, + var enable_backspace_button: Boolean = false, + var enable_return_button: Boolean = false, + var disable_cancel_button: Boolean = false + ) : Serializable + + // Corresponds to Frontend::KeyboardData + @Keep + data class KeyboardData(var result: Int, var text: String) +} |