android: Convert keyboard applet to kotlin and refactor
This commit is contained in:
		| @@ -83,22 +83,22 @@ open class EmulationActivity : AppCompatActivity() { | ||||
|     } | ||||
|  | ||||
|     override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean { | ||||
|         if (event.action == android.view.KeyEvent.ACTION_DOWN) { | ||||
|             if (keyCode == android.view.KeyEvent.KEYCODE_ENTER) { | ||||
|         if (event.action == KeyEvent.ACTION_DOWN) { | ||||
|             if (keyCode == KeyEvent.KEYCODE_ENTER) { | ||||
|                 // Special case, we do not support multiline input, dismiss the keyboard. | ||||
|                 val overlayView: View = | ||||
|                     this.findViewById<View>(R.id.surface_input_overlay) | ||||
|                     this.findViewById(R.id.surface_input_overlay) | ||||
|                 val im = | ||||
|                     overlayView.context.getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager | ||||
|                 im.hideSoftInputFromWindow(overlayView.windowToken, 0); | ||||
|                 im.hideSoftInputFromWindow(overlayView.windowToken, 0) | ||||
|             } else { | ||||
|                 val textChar = event.getUnicodeChar(); | ||||
|                 val textChar = event.unicodeChar | ||||
|                 if (textChar == 0) { | ||||
|                     // No text, button input. | ||||
|                     NativeLibrary.SubmitInlineKeyboardInput(keyCode); | ||||
|                     NativeLibrary.SubmitInlineKeyboardInput(keyCode) | ||||
|                 } else { | ||||
|                     // Text submitted. | ||||
|                     NativeLibrary.SubmitInlineKeyboardText(textChar.toChar().toString()); | ||||
|                     NativeLibrary.SubmitInlineKeyboardText(textChar.toChar().toString()) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -1,264 +0,0 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| package org.yuzu.yuzu_emu.applets; | ||||
|  | ||||
| import android.app.Activity; | ||||
| import android.app.Dialog; | ||||
| import android.content.Context; | ||||
| import android.content.DialogInterface; | ||||
| import android.graphics.Rect; | ||||
| import android.os.Bundle; | ||||
| import android.os.Handler; | ||||
| import android.os.ResultReceiver; | ||||
| import android.text.InputFilter; | ||||
| import android.text.InputType; | ||||
| import android.view.ViewGroup; | ||||
| import android.view.ViewTreeObserver; | ||||
| import android.view.WindowInsets; | ||||
| import android.view.inputmethod.InputMethodManager; | ||||
| import android.widget.EditText; | ||||
| import android.widget.FrameLayout; | ||||
|  | ||||
| import androidx.annotation.NonNull; | ||||
| import androidx.appcompat.app.AlertDialog; | ||||
| import androidx.core.view.ViewCompat; | ||||
| import androidx.fragment.app.DialogFragment; | ||||
|  | ||||
| import com.google.android.material.dialog.MaterialAlertDialogBuilder; | ||||
|  | ||||
| import org.yuzu.yuzu_emu.YuzuApplication; | ||||
| import org.yuzu.yuzu_emu.NativeLibrary; | ||||
| import org.yuzu.yuzu_emu.R; | ||||
| import org.yuzu.yuzu_emu.activities.EmulationActivity; | ||||
|  | ||||
| import java.util.Objects; | ||||
|  | ||||
| public final class SoftwareKeyboard { | ||||
|     /// Corresponds to Service::AM::Applets::SwkbdType | ||||
|     private interface SwkbdType { | ||||
|         int Normal = 0; | ||||
|         int NumberPad = 1; | ||||
|         int Qwerty = 2; | ||||
|         int Unknown3 = 3; | ||||
|         int Latin = 4; | ||||
|         int SimplifiedChinese = 5; | ||||
|         int TraditionalChinese = 6; | ||||
|         int Korean = 7; | ||||
|     }; | ||||
|  | ||||
|     /// Corresponds to Service::AM::Applets::SwkbdPasswordMode | ||||
|     private interface SwkbdPasswordMode { | ||||
|         int Disabled = 0; | ||||
|         int Enabled = 1; | ||||
|     }; | ||||
|  | ||||
|     /// Corresponds to Service::AM::Applets::SwkbdResult | ||||
|     private interface SwkbdResult { | ||||
|         int Ok = 0; | ||||
|         int Cancel = 1; | ||||
|     }; | ||||
|  | ||||
|     public static class KeyboardConfig implements java.io.Serializable { | ||||
|         public String ok_text; | ||||
|         public String header_text; | ||||
|         public String sub_text; | ||||
|         public String guide_text; | ||||
|         public String initial_text; | ||||
|         public short left_optional_symbol_key; | ||||
|         public short right_optional_symbol_key; | ||||
|         public int max_text_length; | ||||
|         public int min_text_length; | ||||
|         public int initial_cursor_position; | ||||
|         public int type; | ||||
|         public int password_mode; | ||||
|         public int text_draw_type; | ||||
|         public int key_disable_flags; | ||||
|         public boolean use_blur_background; | ||||
|         public boolean enable_backspace_button; | ||||
|         public boolean enable_return_button; | ||||
|         public boolean disable_cancel_button; | ||||
|     } | ||||
|  | ||||
|     /// Corresponds to Frontend::KeyboardData | ||||
|     public static class KeyboardData { | ||||
|         public int result; | ||||
|         public String text; | ||||
|  | ||||
|         private KeyboardData(int result, String text) { | ||||
|             this.result = result; | ||||
|             this.text = text; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static class KeyboardDialogFragment extends DialogFragment { | ||||
|         static KeyboardDialogFragment newInstance(KeyboardConfig config) { | ||||
|             KeyboardDialogFragment frag = new KeyboardDialogFragment(); | ||||
|             Bundle args = new Bundle(); | ||||
|             args.putSerializable("config", config); | ||||
|             frag.setArguments(args); | ||||
|             return frag; | ||||
|         } | ||||
|  | ||||
|         @NonNull | ||||
|         @Override | ||||
|         public Dialog onCreateDialog(Bundle savedInstanceState) { | ||||
|             final Activity emulationActivity = getActivity(); | ||||
|             assert emulationActivity != null; | ||||
|  | ||||
|             FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( | ||||
|                     ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); | ||||
|             params.leftMargin = params.rightMargin = | ||||
|                     YuzuApplication.getAppContext().getResources().getDimensionPixelSize( | ||||
|                             R.dimen.dialog_margin); | ||||
|  | ||||
|             KeyboardConfig config = Objects.requireNonNull( | ||||
|                     (KeyboardConfig) requireArguments().getSerializable("config")); | ||||
|  | ||||
|             // Set up the input | ||||
|             EditText editText = new EditText(YuzuApplication.getAppContext()); | ||||
|             editText.setHint(config.initial_text); | ||||
|             editText.setSingleLine(!config.enable_return_button); | ||||
|             editText.setLayoutParams(params); | ||||
|             editText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(config.max_text_length)}); | ||||
|  | ||||
|             // Handle input type | ||||
|             int input_type = 0; | ||||
|             switch (config.type) | ||||
|             { | ||||
|                 case SwkbdType.Normal: | ||||
|                 case SwkbdType.Qwerty: | ||||
|                 case SwkbdType.Unknown3: | ||||
|                 case SwkbdType.Latin: | ||||
|                 case SwkbdType.SimplifiedChinese: | ||||
|                 case SwkbdType.TraditionalChinese: | ||||
|                 case SwkbdType.Korean: | ||||
|                 default: | ||||
|                     input_type = InputType.TYPE_CLASS_TEXT; | ||||
|                     if (config.password_mode == SwkbdPasswordMode.Enabled) | ||||
|                     { | ||||
|                         input_type |= InputType.TYPE_TEXT_VARIATION_PASSWORD; | ||||
|                     } | ||||
|                     break; | ||||
|                 case SwkbdType.NumberPad: | ||||
|                     input_type = InputType.TYPE_CLASS_NUMBER; | ||||
|                     if (config.password_mode == SwkbdPasswordMode.Enabled) | ||||
|                     { | ||||
|                         input_type |= InputType.TYPE_NUMBER_VARIATION_PASSWORD; | ||||
|                     } | ||||
|                     break; | ||||
|             } | ||||
|  | ||||
|             // Apply input type | ||||
|             editText.setInputType(input_type); | ||||
|  | ||||
|             FrameLayout container = new FrameLayout(emulationActivity); | ||||
|             container.addView(editText); | ||||
|  | ||||
|             String headerText = config.header_text.isEmpty() ? emulationActivity.getString(R.string.software_keyboard) : config.header_text; | ||||
|             String okText = config.header_text.isEmpty() ? emulationActivity.getString(android.R.string.ok) : config.ok_text; | ||||
|  | ||||
|             MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(emulationActivity) | ||||
|                     .setTitle(headerText) | ||||
|                     .setView(container); | ||||
|             setCancelable(false); | ||||
|  | ||||
|             builder.setPositiveButton(okText, null); | ||||
|             builder.setNegativeButton(emulationActivity.getString(android.R.string.cancel), null); | ||||
|  | ||||
|             final AlertDialog dialog = builder.create(); | ||||
|             dialog.create(); | ||||
|             if (dialog.getButton(DialogInterface.BUTTON_POSITIVE) != null) { | ||||
|                 dialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener((view) -> { | ||||
|                     data.result = SwkbdResult.Ok; | ||||
|                     data.text = editText.getText().toString(); | ||||
|                     dialog.dismiss(); | ||||
|  | ||||
|                     synchronized (finishLock) { | ||||
|                         finishLock.notifyAll(); | ||||
|                     } | ||||
|                 }); | ||||
|             } | ||||
|             if (dialog.getButton(DialogInterface.BUTTON_NEUTRAL) != null) { | ||||
|                 dialog.getButton(DialogInterface.BUTTON_NEUTRAL).setOnClickListener((view) -> { | ||||
|                     data.result = SwkbdResult.Ok; | ||||
|                     dialog.dismiss(); | ||||
|                     synchronized (finishLock) { | ||||
|                         finishLock.notifyAll(); | ||||
|                     } | ||||
|                 }); | ||||
|             } | ||||
|             if (dialog.getButton(DialogInterface.BUTTON_NEGATIVE) != null) { | ||||
|                 dialog.getButton(DialogInterface.BUTTON_NEGATIVE).setOnClickListener((view) -> { | ||||
|                     data.result = SwkbdResult.Cancel; | ||||
|                     dialog.dismiss(); | ||||
|                     synchronized (finishLock) { | ||||
|                         finishLock.notifyAll(); | ||||
|                     } | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             return dialog; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private static KeyboardData data; | ||||
|     private static final Object finishLock = new Object(); | ||||
|  | ||||
|     private static void ExecuteNormalImpl(KeyboardConfig config) { | ||||
|         final EmulationActivity emulationActivity = NativeLibrary.sEmulationActivity.get(); | ||||
|  | ||||
|         data = new KeyboardData(SwkbdResult.Cancel, ""); | ||||
|  | ||||
|         KeyboardDialogFragment fragment = KeyboardDialogFragment.newInstance(config); | ||||
|         fragment.show(emulationActivity.getSupportFragmentManager(), "keyboard"); | ||||
|     } | ||||
|  | ||||
|     private static void ExecuteInlineImpl(KeyboardConfig config) { | ||||
|         final EmulationActivity emulationActivity = NativeLibrary.sEmulationActivity.get(); | ||||
|  | ||||
|         var overlayView = emulationActivity.findViewById(R.id.surface_input_overlay); | ||||
|         InputMethodManager im = (InputMethodManager)overlayView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); | ||||
|         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. | ||||
|         final Handler handler = new Handler(); | ||||
|         final int delayMs = 500; | ||||
|         handler.postDelayed(new Runnable() { | ||||
|             public void run() { | ||||
|                 var insets = ViewCompat.getRootWindowInsets(overlayView); | ||||
|                 var isKeyboardVisible = insets.isVisible(WindowInsets.Type.ime()); | ||||
|                 if (isKeyboardVisible) { | ||||
|                     handler.postDelayed(this, delayMs); | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 // No longer visible, submit the result. | ||||
|                 NativeLibrary.SubmitInlineKeyboardInput(android.view.KeyEvent.KEYCODE_ENTER); | ||||
|             } | ||||
|         }, delayMs); | ||||
|     } | ||||
|  | ||||
|     public static KeyboardData ExecuteNormal(KeyboardConfig config) { | ||||
|         NativeLibrary.sEmulationActivity.get().runOnUiThread(() -> ExecuteNormalImpl(config)); | ||||
|  | ||||
|         synchronized (finishLock) { | ||||
|             try { | ||||
|                 finishLock.wait(); | ||||
|             } catch (Exception ignored) { | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return data; | ||||
|     } | ||||
|  | ||||
|     public static void ExecuteInline(KeyboardConfig config) { | ||||
|         NativeLibrary.sEmulationActivity.get().runOnUiThread(() -> ExecuteInlineImpl(config)); | ||||
|     } | ||||
|  | ||||
|     public static void ShowError(String error) { | ||||
|         NativeLibrary.displayAlertMsg( | ||||
|                 YuzuApplication.getAppContext().getResources().getString(R.string.software_keyboard), | ||||
|                 error, false); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,117 @@ | ||||
| // 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.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 | ||||
|  | ||||
| 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 | ||||
|     } | ||||
|  | ||||
|     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 | ||||
|     data class KeyboardData(var result: Int, var text: String) | ||||
| } | ||||
| @@ -0,0 +1,100 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| package org.yuzu.yuzu_emu.applets.keyboard.ui | ||||
|  | ||||
| import android.app.Dialog | ||||
| import android.content.DialogInterface | ||||
| import android.os.Bundle | ||||
| import android.text.InputFilter | ||||
| import android.text.InputType | ||||
| import androidx.fragment.app.DialogFragment | ||||
| import com.google.android.material.dialog.MaterialAlertDialogBuilder | ||||
| import org.yuzu.yuzu_emu.R | ||||
| import org.yuzu.yuzu_emu.applets.keyboard.SoftwareKeyboard | ||||
| import org.yuzu.yuzu_emu.applets.keyboard.SoftwareKeyboard.KeyboardConfig | ||||
| import org.yuzu.yuzu_emu.databinding.DialogEditTextBinding | ||||
| import org.yuzu.yuzu_emu.utils.SerializableHelper.serializable | ||||
|  | ||||
| class KeyboardDialogFragment : DialogFragment() { | ||||
|     private lateinit var binding: DialogEditTextBinding | ||||
|     private lateinit var config: KeyboardConfig | ||||
|  | ||||
|     override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { | ||||
|         binding = DialogEditTextBinding.inflate(layoutInflater) | ||||
|         config = requireArguments().serializable(CONFIG)!! | ||||
|  | ||||
|         // Set up the input | ||||
|         binding.editText.hint = config.initial_text | ||||
|         binding.editText.isSingleLine = !config.enable_return_button | ||||
|         binding.editText.filters = | ||||
|             arrayOf<InputFilter>(InputFilter.LengthFilter(config.max_text_length)) | ||||
|  | ||||
|         // Handle input type | ||||
|         var inputType: Int | ||||
|         when (config.type) { | ||||
|             SoftwareKeyboard.SwkbdType.Normal.ordinal, | ||||
|             SoftwareKeyboard.SwkbdType.Qwerty.ordinal, | ||||
|             SoftwareKeyboard.SwkbdType.Unknown3.ordinal, | ||||
|             SoftwareKeyboard.SwkbdType.Latin.ordinal, | ||||
|             SoftwareKeyboard.SwkbdType.SimplifiedChinese.ordinal, | ||||
|             SoftwareKeyboard.SwkbdType.TraditionalChinese.ordinal, | ||||
|             SoftwareKeyboard.SwkbdType.Korean.ordinal -> { | ||||
|                 inputType = InputType.TYPE_CLASS_TEXT | ||||
|                 if (config.password_mode == SoftwareKeyboard.SwkbdPasswordMode.Enabled.ordinal) { | ||||
|                     inputType = inputType or InputType.TYPE_TEXT_VARIATION_PASSWORD | ||||
|                 } | ||||
|             } | ||||
|             SoftwareKeyboard.SwkbdType.NumberPad.ordinal -> { | ||||
|                 inputType = InputType.TYPE_CLASS_NUMBER | ||||
|                 if (config.password_mode == SoftwareKeyboard.SwkbdPasswordMode.Enabled.ordinal) { | ||||
|                     inputType = inputType or InputType.TYPE_NUMBER_VARIATION_PASSWORD | ||||
|                 } | ||||
|             } | ||||
|             else -> { | ||||
|                 inputType = InputType.TYPE_CLASS_TEXT | ||||
|                 if (config.password_mode == SoftwareKeyboard.SwkbdPasswordMode.Enabled.ordinal) { | ||||
|                     inputType = inputType or InputType.TYPE_TEXT_VARIATION_PASSWORD | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         binding.editText.inputType = inputType | ||||
|  | ||||
|         val headerText = | ||||
|             config.header_text!!.ifEmpty { resources.getString(R.string.software_keyboard) } | ||||
|         val okText = | ||||
|             if (config.header_text!!.isEmpty()) resources.getString(android.R.string.ok) else config.ok_text!! | ||||
|  | ||||
|         return MaterialAlertDialogBuilder(requireContext()) | ||||
|             .setTitle(headerText) | ||||
|             .setView(binding.root) | ||||
|             .setPositiveButton(okText) { _, _ -> | ||||
|                 SoftwareKeyboard.data.result = SoftwareKeyboard.SwkbdResult.Ok.ordinal | ||||
|                 SoftwareKeyboard.data.text = binding.editText.text.toString() | ||||
|             } | ||||
|             .setNegativeButton(resources.getString(android.R.string.cancel)) { _, _ -> | ||||
|                 SoftwareKeyboard.data.result = SoftwareKeyboard.SwkbdResult.Cancel.ordinal | ||||
|             } | ||||
|             .create() | ||||
|     } | ||||
|  | ||||
|     override fun onDismiss(dialog: DialogInterface) { | ||||
|         super.onDismiss(dialog) | ||||
|         synchronized(SoftwareKeyboard.dataLock) { | ||||
|             SoftwareKeyboard.dataLock.notifyAll() | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     companion object { | ||||
|         const val TAG = "KeyboardDialogFragment" | ||||
|         const val CONFIG = "keyboard_config" | ||||
|  | ||||
|         fun newInstance(config: KeyboardConfig?): KeyboardDialogFragment { | ||||
|             val frag = KeyboardDialogFragment() | ||||
|             val args = Bundle() | ||||
|             args.putSerializable(CONFIG, config) | ||||
|             frag.arguments = args | ||||
|             return frag | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -253,19 +253,19 @@ void AndroidKeyboard::SubmitNormalText(const ResultData& data) const { | ||||
|  | ||||
| void InitJNI(JNIEnv* env) { | ||||
|     s_software_keyboard_class = reinterpret_cast<jclass>( | ||||
|         env->NewGlobalRef(env->FindClass("org/yuzu/yuzu_emu/applets/SoftwareKeyboard"))); | ||||
|         env->NewGlobalRef(env->FindClass("org/yuzu/yuzu_emu/applets/keyboard/SoftwareKeyboard"))); | ||||
|     s_keyboard_config_class = reinterpret_cast<jclass>(env->NewGlobalRef( | ||||
|         env->FindClass("org/yuzu/yuzu_emu/applets/SoftwareKeyboard$KeyboardConfig"))); | ||||
|         env->FindClass("org/yuzu/yuzu_emu/applets/keyboard/SoftwareKeyboard$KeyboardConfig"))); | ||||
|     s_keyboard_data_class = reinterpret_cast<jclass>(env->NewGlobalRef( | ||||
|         env->FindClass("org/yuzu/yuzu_emu/applets/SoftwareKeyboard$KeyboardData"))); | ||||
|         env->FindClass("org/yuzu/yuzu_emu/applets/keyboard/SoftwareKeyboard$KeyboardData"))); | ||||
|  | ||||
|     s_swkbd_execute_normal = env->GetStaticMethodID( | ||||
|         s_software_keyboard_class, "ExecuteNormal", | ||||
|         "(Lorg/yuzu/yuzu_emu/applets/SoftwareKeyboard$KeyboardConfig;)Lorg/yuzu/yuzu_emu/" | ||||
|         "applets/SoftwareKeyboard$KeyboardData;"); | ||||
|         s_software_keyboard_class, "executeNormal", | ||||
|         "(Lorg/yuzu/yuzu_emu/applets/keyboard/SoftwareKeyboard$KeyboardConfig;)Lorg/yuzu/yuzu_emu/" | ||||
|         "applets/keyboard/SoftwareKeyboard$KeyboardData;"); | ||||
|     s_swkbd_execute_inline = | ||||
|         env->GetStaticMethodID(s_software_keyboard_class, "ExecuteInline", | ||||
|                                "(Lorg/yuzu/yuzu_emu/applets/SoftwareKeyboard$KeyboardConfig;)V"); | ||||
|         env->GetStaticMethodID(s_software_keyboard_class, "executeInline", | ||||
|                                "(Lorg/yuzu/yuzu_emu/applets/keyboard/SoftwareKeyboard$KeyboardConfig;)V"); | ||||
| } | ||||
|  | ||||
| void CleanupJNI(JNIEnv* env) { | ||||
|   | ||||
							
								
								
									
										23
									
								
								src/android/app/src/main/res/layout/dialog_edit_text.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/android/app/src/main/res/layout/dialog_edit_text.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <androidx.constraintlayout.widget.ConstraintLayout | ||||
|     xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="match_parent"> | ||||
|  | ||||
|     <com.google.android.material.textfield.TextInputLayout | ||||
|         android:id="@+id/edit_text_layout" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_margin="24dp" | ||||
|         app:layout_constraintTop_toTopOf="parent"> | ||||
|  | ||||
|         <com.google.android.material.textfield.TextInputEditText | ||||
|             android:id="@+id/edit_text" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:inputType="none" /> | ||||
|  | ||||
|     </com.google.android.material.textfield.TextInputLayout> | ||||
|  | ||||
| </androidx.constraintlayout.widget.ConstraintLayout> | ||||
		Reference in New Issue
	
	Block a user