android.rs 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2024 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use miniquad::native::android::{self, ndk_sys, ndk_utils};
  19. use std::sync::{LazyLock, Mutex as SyncMutex};
  20. struct GlobalData {
  21. inp_conn: ndk_sys::jobject,
  22. sender: Option<async_channel::Sender<AndroidSuggestEvent>>,
  23. }
  24. unsafe impl Send for GlobalData {}
  25. unsafe impl Sync for GlobalData {}
  26. static GLOBALS: LazyLock<SyncMutex<GlobalData>> =
  27. LazyLock::new(|| SyncMutex::new(GlobalData { inp_conn: std::ptr::null_mut(), sender: None }));
  28. #[no_mangle]
  29. pub unsafe extern "C" fn Java_autosuggest_CustomInputConnection_setup() {
  30. let env = android::attach_jni_env();
  31. let inp_conn = ndk_utils::new_object!(env, "autosuggest/CustomInputConnection", "()V");
  32. assert!(!inp_conn.is_null());
  33. let inp_conn = ndk_utils::new_global_ref!(env, inp_conn);
  34. GLOBALS.lock().unwrap().inp_conn = inp_conn;
  35. }
  36. pub enum AndroidSuggestEvent {
  37. CommitText(String),
  38. EditText(String),
  39. }
  40. #[no_mangle]
  41. pub unsafe extern "C" fn Java_autosuggest_CustomInputConnection_onCommitText(
  42. env: *mut ndk_sys::JNIEnv,
  43. _: ndk_sys::jobject,
  44. text: ndk_sys::jobject,
  45. ) {
  46. let text = ndk_utils::get_utf_str!(env, text);
  47. //debug!(target: "android", "onCommitText({text})");
  48. if let Some(sender) = &GLOBALS.lock().unwrap().sender {
  49. let _ = sender.try_send(AndroidSuggestEvent::CommitText(text.to_string()));
  50. }
  51. }
  52. #[no_mangle]
  53. pub unsafe extern "C" fn Java_autosuggest_CustomInputConnection_onEndEdit(
  54. env: *mut ndk_sys::JNIEnv,
  55. _: ndk_sys::jobject,
  56. text: ndk_sys::jobject,
  57. ) {
  58. let text = ndk_utils::get_utf_str!(env, text);
  59. //debug!(target: "android", "onEditText({text})");
  60. if let Some(sender) = &GLOBALS.lock().unwrap().sender {
  61. let _ = sender.try_send(AndroidSuggestEvent::EditText(text.to_string()));
  62. }
  63. }
  64. pub fn set_sender(sender: async_channel::Sender<AndroidSuggestEvent>) {
  65. GLOBALS.lock().unwrap().sender = Some(sender);
  66. }
  67. pub fn reset_autosuggest() {
  68. let env = unsafe { android::attach_jni_env() };
  69. let mut globals = GLOBALS.lock().unwrap();
  70. if globals.inp_conn.is_null() {
  71. error!(target: "android", "InputConnection is not ready!");
  72. return
  73. }
  74. unsafe {
  75. ndk_utils::call_void_method!(env, globals.inp_conn, "reset", "()V");
  76. }
  77. }