From 60cbf59ddfe6486689e79415f680afc24e971755 Mon Sep 17 00:00:00 2001 From: Logan McNaughton <848146+loganmc10@users.noreply.github.com> Date: Mon, 25 May 2026 21:35:04 +0200 Subject: [PATCH] add intent for input profile (#952) * add intent for input profile * more * more --- src/lib.rs | 8 ++--- src/ui/android.rs | 78 ++++++++++++++++++++++++++++++++++++++++++----- src/ui/gui.rs | 2 +- 3 files changed, 75 insertions(+), 13 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index cbd2070..a519a13 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -316,11 +316,9 @@ async fn android_main(app: slint::android::AndroidApp) { if let Ok(weak_app_window) = android::WEAK_SLINT_WINDOW.lock() && let Some(weak_app_window) = weak_app_window.as_ref() { - { - weak_app_window - .upgrade_in_event_loop(move |handle| ui::gui::save_settings(&handle)) - .unwrap(); - } + weak_app_window + .upgrade_in_event_loop(move |handle| ui::gui::save_settings(&handle)) + .unwrap(); } } _ => {} diff --git a/src/ui/android.rs b/src/ui/android.rs index 0b77497..e7bcc64 100644 --- a/src/ui/android.rs +++ b/src/ui/android.rs @@ -5,7 +5,8 @@ use jni::sys::jint; use jni::{Env, EnvUnowned, JavaVM, bind_java_type}; use std::os::fd::FromRawFd; -pub const REQUEST_SELECT_ROM: jint = 1; +const REQUEST_SELECT_ROM: jint = 1; +const CONFIGURE_INPUT_PROFILE: jint = 2; pub static ANDROID_APP: std::sync::Mutex> = std::sync::Mutex::new(None); @@ -60,14 +61,27 @@ bind_java_type! { static FLAG_GRANT_READ_URI_PERMISSION: jint, }, constructors { - fn new(action: JString), + fn new(), + fn with_action(action: JString), }, methods { fn set_data(uri: AndroidUri) -> AndroidIntent, fn set_type(r#type: JString) -> AndroidIntent, fn add_category(category: JString) -> AndroidIntent, fn get_data() -> AndroidUri, - fn put_extra(extra: JString, value: JString) -> AndroidIntent, + fn put_extra_string { + sig = (extra: JString, value: JString) -> AndroidIntent, + name = "putExtra", + }, + fn put_extra_boolean { + sig = (extra: JString, value: jboolean) -> AndroidIntent, + name = "putExtra", + }, + fn put_extra_int { + sig = (extra: JString, value: jint) -> AndroidIntent, + name = "putExtra", + }, + fn set_class_name(package_name: JString, class_name: JString) -> AndroidIntent, }, } @@ -127,7 +141,49 @@ pub struct ControllerInfo { pub descriptor: String, } -pub fn configure_input_profile(_profile_name: slint::SharedString, _dinput: bool, _deadzone: i32) {} +pub fn configure_input_profile(profile_name: slint::SharedString, dinput: bool, deadzone: i32) { + if let Some(vm) = get_vm() { + if let Err(err) = vm.attach_current_thread(|env| { + start_n64_activity_on_jvm(env, profile_name.to_string(), dinput, deadzone) + }) { + eprintln!("JNI error while starting N64Activity: {err:?}"); + } + } +} + +fn start_n64_activity_on_jvm( + env: &mut Env<'_>, + profile_name: String, + dinput: bool, + deadzone: i32, +) -> jni::errors::Result<()> { + if let Ok(app) = ANDROID_APP.lock() + && let Some(app) = app.as_ref() + { + let raw_activity_global = app.activity_as_ptr() as jni::sys::jobject; + let activity = unsafe { env.as_cast_raw::>(&raw_activity_global)? }; + + let package_name = JString::from_str(env, "io.github.gopher64.gopher64")?; + let class_name = JString::from_str(env, "io.github.gopher64.gopher64.N64Activity")?; + + let profile_name_key = JString::from_str(env, "profile_name")?; + let profile_name_value = JString::from_str(env, profile_name)?; + let dinput_key = JString::from_str(env, "dinput")?; + let deadzone_key = JString::from_str(env, "deadzone")?; + let intent = AndroidIntent::new(env)? + .set_class_name(env, &package_name, &class_name)? + .put_extra_string(env, &profile_name_key, &profile_name_value)? + .put_extra_boolean(env, &dinput_key, dinput)? + .put_extra_int(env, &deadzone_key, deadzone)?; + + activity + .as_ref() + .start_activity_for_result(env, &intent, CONFIGURE_INPUT_PROFILE)?; + Ok(()) + } else { + Err(jni::errors::Error::UninitializedJavaVM) + } +} pub fn run_rom( _file_path: std::path::PathBuf, @@ -233,7 +289,7 @@ fn open_uri_on_jvm(env: &mut Env<'_>, path: &str) -> jni::errors::Result<()> { let uri = AndroidUri::parse(env, &uri_string)?; let action_view = AndroidIntent::ACTION_VIEW(env)?; - let intent = AndroidIntent::new(env, &action_view)?.set_data(env, &uri)?; + let intent = AndroidIntent::with_action(env, &action_view)?.set_data(env, &uri)?; activity.as_ref().start_activity(env, &intent)?; Ok(()) @@ -282,13 +338,13 @@ fn select_rom_on_jvm(env: &mut Env<'_>, rom_dir: String) -> jni::errors::Result< let action = AndroidIntent::ACTION_OPEN_DOCUMENT(env)?; let category = AndroidIntent::CATEGORY_OPENABLE(env)?; let mime_type = JString::from_str(env, "*/*")?; - let mut intent = AndroidIntent::new(env, &action)? + let mut intent = AndroidIntent::with_action(env, &action)? .set_type(env, &mime_type)? .add_category(env, &category)?; if !rom_dir.is_empty() { let start_dir = JString::from_str(env, rom_dir)?; let extra_initial_uri = DocumentsContract::EXTRA_INITIAL_URI(env)?; - intent = intent.put_extra(env, &extra_initial_uri, &start_dir)?; + intent = intent.put_extra_string(env, &extra_initial_uri, &start_dir)?; } activity.start_activity_for_result(env, &intent, REQUEST_SELECT_ROM)?; @@ -425,6 +481,14 @@ pub extern "system" fn Java_io_github_gopher64_gopher64_SlintActivity_nativeOnAc } } } + CONFIGURE_INPUT_PROFILE => { + if let Ok(weak_app_window) = WEAK_SLINT_WINDOW.lock() + && let Some(weak_app_window) = weak_app_window.as_ref() + { + let config = ui::config::Config::new(); + ui::gui::update_input_profiles(&weak_app_window, &config); + } + } _ => {} } } diff --git a/src/ui/gui.rs b/src/ui/gui.rs index a1fedd1..55d2d43 100644 --- a/src/ui/gui.rs +++ b/src/ui/gui.rs @@ -189,7 +189,7 @@ fn settings_window(app: &AppWindow, config: &ui::config::Config) { } } -fn update_input_profiles(weak: &slint::Weak, config: &ui::config::Config) { +pub fn update_input_profiles(weak: &slint::Weak, config: &ui::config::Config) { let profiles = input_profiles(config); let config_bindings = config.input.input_profile_binding.clone(); weak.upgrade_in_event_loop(move |handle| {