android.rs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2025 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::{
  20. path::PathBuf,
  21. sync::{LazyLock, Mutex as SyncMutex},
  22. };
  23. struct GlobalData {
  24. sender: Option<async_channel::Sender<AndroidSuggestEvent>>,
  25. }
  26. unsafe impl Send for GlobalData {}
  27. unsafe impl Sync for GlobalData {}
  28. static GLOBALS: LazyLock<SyncMutex<GlobalData>> =
  29. LazyLock::new(|| SyncMutex::new(GlobalData { sender: None }));
  30. pub enum AndroidSuggestEvent {
  31. Compose { text: String, cursor_pos: i32, is_commit: bool },
  32. ComposeRegion { start: usize, end: usize },
  33. }
  34. #[no_mangle]
  35. pub unsafe extern "C" fn Java_autosuggest_CustomInputConnection_onCompose(
  36. env: *mut ndk_sys::JNIEnv,
  37. _: ndk_sys::jobject,
  38. text: ndk_sys::jobject,
  39. cursor_pos: ndk_sys::jint,
  40. is_commit: ndk_sys::jboolean,
  41. ) {
  42. let text = ndk_utils::get_utf_str!(env, text);
  43. if let Some(sender) = &GLOBALS.lock().unwrap().sender {
  44. let _ = sender.try_send(AndroidSuggestEvent::Compose {
  45. text: text.to_string(),
  46. cursor_pos,
  47. is_commit: is_commit != 0,
  48. });
  49. }
  50. }
  51. #[no_mangle]
  52. pub unsafe extern "C" fn Java_autosuggest_CustomInputConnection_onSetComposeRegion(
  53. env: *mut ndk_sys::JNIEnv,
  54. _: ndk_sys::jobject,
  55. start: ndk_sys::jint,
  56. end: ndk_sys::jint,
  57. ) {
  58. let begin = std::cmp::min(start, end);
  59. let end = std::cmp::max(start, end);
  60. if begin < 0 || end < 0 {
  61. warn!(target: "android", "setComposeRegion({start}, {end}) is < 0 so skipping");
  62. return
  63. }
  64. let start = begin as usize;
  65. let end = end as usize;
  66. if let Some(sender) = &GLOBALS.lock().unwrap().sender {
  67. let _ = sender.try_send(AndroidSuggestEvent::ComposeRegion { start, end });
  68. }
  69. }
  70. pub fn set_sender(sender: async_channel::Sender<AndroidSuggestEvent>) {
  71. GLOBALS.lock().unwrap().sender = Some(sender);
  72. }
  73. pub fn cancel_composition() {
  74. unsafe {
  75. let env = android::attach_jni_env();
  76. ndk_utils::call_void_method!(env, android::ACTIVITY, "cancelComposition", "()V");
  77. }
  78. }
  79. pub fn get_keyboard_height() -> usize {
  80. unsafe {
  81. let env = android::attach_jni_env();
  82. ndk_utils::call_int_method!(env, android::ACTIVITY, "getKeyboardHeight", "()I") as usize
  83. }
  84. }
  85. pub fn get_appdata_path() -> PathBuf {
  86. let path = unsafe {
  87. let env = android::attach_jni_env();
  88. let text = ndk_utils::call_object_method!(
  89. env,
  90. android::ACTIVITY,
  91. "getAppDataPath",
  92. "()Ljava/lang/String;"
  93. );
  94. ndk_utils::get_utf_str!(env, text).to_string()
  95. };
  96. path.into()
  97. }
  98. pub fn get_external_storage_path() -> PathBuf {
  99. let path = unsafe {
  100. let env = android::attach_jni_env();
  101. let text = ndk_utils::call_object_method!(
  102. env,
  103. android::ACTIVITY,
  104. "getExternalStoragePath",
  105. "()Ljava/lang/String;"
  106. );
  107. ndk_utils::get_utf_str!(env, text).to_string()
  108. };
  109. path.into()
  110. }