From 172d10d7cb95089e694bc9fa4948fc165d14ef80 Mon Sep 17 00:00:00 2001 From: Logan McNaughton <848146+loganmc10@users.noreply.github.com> Date: Wed, 6 May 2026 09:44:39 +0200 Subject: [PATCH] update controllers when clicking on controller config (#841) * update controllers when clicking on controller config * more * more * more * more * more * more * more * more * more * more * more * more * more * more * more * more * more * more * more * more * more --- src/device.rs | 2 +- src/main.rs | 43 +++++---- src/ui.rs | 36 +------ src/ui/gui.rs | 160 ++++++++++++++++--------------- src/ui/gui/appwindow.slint | 6 +- src/ui/gui/controller_page.slint | 9 +- src/ui/input.rs | 73 +++++++++----- src/ui/netplay.rs | 10 +- src/ui/video.rs | 2 + 9 files changed, 175 insertions(+), 166 deletions(-) diff --git a/src/device.rs b/src/device.rs index ba314aae..36c21c5e 100644 --- a/src/device.rs +++ b/src/device.rs @@ -207,7 +207,7 @@ pub fn get_rom_contents(file_path: &std::path::Path) -> Option> { pub struct Device { #[serde(skip)] pub netplay: Option, - #[serde(skip, default = "ui::Ui::default")] + #[serde(skip, default = "ui::Ui::new")] pub ui: ui::Ui, pub byte_swap: usize, pub save_state: bool, diff --git a/src/main.rs b/src/main.rs index a262f875..e0b558e1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -249,10 +249,10 @@ async fn main() -> std::io::Result<()> { ui::usb::close(shutdown_tx); } } else if std::env::args().count() > 1 { - let mut ui = ui::Ui::new(); + let mut config = ui::config::Config::new(); if args.clear_input_bindings { - ui::input::clear_bindings(&mut ui); + ui::input::clear_bindings(&mut config); return Ok(()); } if let Some(port) = args.port @@ -260,34 +260,35 @@ async fn main() -> std::io::Result<()> { { return Err(Error::other("Port must be between 1 and 4")); } - if args.list_controllers { - let controllers = ui::input::get_controller_names(&ui); - for (i, controller) in controllers.iter().enumerate() { - println!("Controller {i}: {controller}"); - } - return Ok(()); - } if let Some(profile) = args.configure_input_profile { ui::input::configure_input_profile( - &mut ui, + &mut config, profile, args.use_dinput, args.deadzone.unwrap_or(ui::input::DEADZONE_DEFAULT), ); return Ok(()); } - if let Some(assign_controller) = args.assign_controller { - let Some(port) = args.port else { - return Err(Error::other("Must specify port number")); - }; - ui::input::assign_controller(&mut ui, assign_controller, port); - } - if let Some(profile) = args.bind_input_profile { - let Some(port) = args.port else { - return Err(Error::other("Must specify port number")); - }; - ui::input::bind_input_profile(&mut ui, profile, port); + if args.list_controllers { + let controllers = ui::input::get_controller_names(); + for (i, controller) in controllers.iter().enumerate() { + println!("Controller {i}: {controller}"); + } + } else { + if let Some(assign_controller) = args.assign_controller { + let Some(port) = args.port else { + return Err(Error::other("Must specify port number")); + }; + ui::input::assign_controller(&mut config, assign_controller - 1, port); + } + if let Some(profile) = args.bind_input_profile { + let Some(port) = args.port else { + return Err(Error::other("Must specify port number")); + }; + ui::input::bind_input_profile(&mut config, profile, port); + } } + unsafe { sdl3_sys::init::SDL_Quit() }; } else { #[cfg(feature = "gui")] { diff --git a/src/ui.rs b/src/ui.rs index cf6a34cf..d4dd8324 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -38,7 +38,6 @@ pub struct Audio { } pub struct Input { - pub joysticks: Vec, pub keyboard_state: *const bool, pub controllers: [input::Controllers; 4], } @@ -77,7 +76,6 @@ pub struct Ui { pub config: config::Config, pub game_id: String, pub game_hash: String, - pub with_sdl: bool, pub audio: Audio, pub input: Input, pub storage: Storage, @@ -85,17 +83,6 @@ pub struct Ui { pub usb: Usb, } -impl Drop for Ui { - fn drop(&mut self) { - if self.with_sdl { - unsafe { - sdl3_ttf_sys::ttf::TTF_Quit(); - sdl3_sys::init::SDL_Quit(); - } - } - } -} - pub fn sdl_init(flag: sdl3_sys::init::SDL_InitFlags) { unsafe { if sdl3_sys::init::SDL_WasInit(flag) == 0 && !sdl3_sys::init::SDL_InitSubSystem(flag) { @@ -141,7 +128,7 @@ pub fn get_dirs() -> Dirs { } impl Ui { - fn construct_ui(joysticks: Vec, with_sdl: bool) -> Ui { + pub fn new() -> Ui { let dirs = get_dirs(); let (fps_tx, fps_rx) = tokio::sync::mpsc::channel(1000); @@ -179,7 +166,6 @@ impl Ui { }, ], keyboard_state: std::ptr::null_mut(), - joysticks, }, storage: Storage { save_state_slot: 0, @@ -241,26 +227,6 @@ impl Ui { cart_rx: None, }, dirs, - with_sdl, } } - - pub fn default() -> Ui { - Self::construct_ui(vec![], false) - } - - pub fn new() -> Ui { - sdl_init(sdl3_sys::init::SDL_INIT_GAMEPAD); - let mut num_joysticks = 0; - let joysticks = unsafe { sdl3_sys::joystick::SDL_GetJoysticks(&mut num_joysticks) }; - if joysticks.is_null() { - panic!("Could not get joystick list"); - } - let mut joystick_vec = vec![]; - for i in 0..num_joysticks { - joystick_vec.push(unsafe { *joysticks.add(i as usize) }); - } - unsafe { sdl3_sys::stdinc::SDL_free(joysticks as *mut std::ffi::c_void) } - Self::construct_ui(joystick_vec, true) - } } diff --git a/src/ui/gui.rs b/src/ui/gui.rs index e69c4036..322a2c11 100644 --- a/src/ui/gui.rs +++ b/src/ui/gui.rs @@ -53,18 +53,13 @@ fn check_latest_version(weak: slint::Weak) { }); } -fn run_with_path( - weak: slint::Weak, - path: std::path::PathBuf, - controller_paths: &[Option], -) { - let controller_paths = controller_paths.to_owned(); +fn run_with_path(weak: slint::Weak, path: std::path::PathBuf) { let weak2 = weak.clone(); weak.upgrade_in_event_loop(move |handle| { if handle.get_game_running() { return; } - save_settings(&handle, &controller_paths); + save_settings(&handle); run_rom( path, @@ -87,23 +82,18 @@ fn run_with_path( .unwrap(); } -fn file_dropped(app: &AppWindow, controller_paths: &[Option]) { +fn file_dropped(app: &AppWindow) { let weak = app.as_weak(); - let controller_paths = controller_paths.to_owned(); app.window() .on_winit_window_event(move |_winit_window, event| { if let slint::winit_030::winit::event::WindowEvent::DroppedFile(path) = event { - run_with_path(weak.clone(), path.to_path_buf(), &controller_paths); + run_with_path(weak.clone(), path.to_path_buf()); } slint::winit_030::EventResult::Propagate }); } -fn local_game_window( - app: &AppWindow, - config: &ui::config::Config, - controller_paths: &[Option], -) { +fn local_game_window(app: &AppWindow, config: &ui::config::Config) { let dirs = ui::get_dirs(); app.set_recent_roms(slint::ModelRc::from(std::rc::Rc::new( @@ -128,26 +118,18 @@ fn local_game_window( ))); let weak = app.as_weak(); - let owned_controller_paths = controller_paths.to_owned(); app.on_open_rom_button_clicked(move || { - let controller_paths = owned_controller_paths.clone(); weak.upgrade_in_event_loop(move |handle| { - save_settings(&handle, &controller_paths); + save_settings(&handle); open_rom(&handle) }) .unwrap(); }); let weak = app.as_weak(); - let owned_controller_paths = controller_paths.to_owned(); app.on_recent_rom_button_clicked(move |rom| { - let controller_paths = owned_controller_paths.clone(); weak.upgrade_in_event_loop(move |handle| { - run_with_path( - handle.as_weak(), - std::path::PathBuf::from(rom.to_string()), - &controller_paths, - ); + run_with_path(handle.as_weak(), std::path::PathBuf::from(rom.to_string())); }) .unwrap(); }); @@ -158,7 +140,7 @@ fn local_game_window( eprintln!("Error opening saves folder: {}", e); } }); - file_dropped(app, controller_paths); + file_dropped(app); } fn input_profiles(config: &ui::config::Config) -> Vec { @@ -195,7 +177,6 @@ fn settings_window(app: &AppWindow, config: &ui::config::Config) { 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(); - let weak2 = weak.clone(); weak.upgrade_in_event_loop(move |handle| { let profile_bindings = slint::VecModel::default(); for (i, input_profile_binding) in handle.get_selected_profile_binding().iter().enumerate() { @@ -221,16 +202,6 @@ fn update_input_profiles(weak: &slint::Weak, config: &ui::config::Con handle .set_selected_profile_binding(slint::ModelRc::from(std::rc::Rc::new(profile_bindings))); - - // this is a workaround to make the input profile combobox update - handle.set_blank_profiles(true); - slint::Timer::single_shot(std::time::Duration::from_millis(200), move || { - weak2 - .upgrade_in_event_loop(move |handle| { - handle.set_blank_profiles(false); - }) - .unwrap(); - }); }) .unwrap(); } @@ -247,12 +218,7 @@ fn clear_gb_paths(weak: &slint::Weak, player: i32) { .unwrap(); } -fn controller_window( - app: &AppWindow, - config: &ui::config::Config, - controller_names: &[String], - controller_paths: &[Option], -) { +fn controller_window(app: &AppWindow, config: &ui::config::Config) { app.set_emulate_vru(config.input.emulate_vru); app.set_controller_enabled(slint::ModelRc::from(std::rc::Rc::new( @@ -287,28 +253,66 @@ fn controller_window( update_input_profiles(&app.as_weak(), config); - app.set_controller_names(slint::ModelRc::from(std::rc::Rc::new( - slint::VecModel::from( - controller_names - .iter() - .map(|x| x.into()) - .collect::>(), - ), + app.set_controller_changed(slint::ModelRc::from(std::rc::Rc::new( + slint::VecModel::from(vec![false, false, false, false]), ))); - let controller_changed = slint::VecModel::default(); - let selected_controllers = slint::VecModel::default(); - for selected in config.input.controller_assignment.iter() { - let selected_index = controller_paths - .iter() - .position(|path| selected == path) - .unwrap_or(0) as i32; - selected_controllers.push(selected_index); - controller_changed.push(false); - } - app.set_selected_controller(slint::ModelRc::from(std::rc::Rc::new(selected_controllers))); + let config_controller_assignment = config.input.controller_assignment.clone(); + let weak_app = app.as_weak(); + app.on_controller_window_created(move || { + let controller_assignment = config_controller_assignment.clone(); + weak_app + .upgrade_in_event_loop(move |handle| { + let mut current_selected_paths = vec![None; 4]; + for (i, selected_controller) in handle.get_selected_controller().iter().enumerate() + { + current_selected_paths[i] = handle + .get_controller_paths() + .row_data(selected_controller as usize); + } - app.set_controller_changed(slint::ModelRc::from(std::rc::Rc::new(controller_changed))); + let controller_names = ui::input::get_controller_names(); + handle.set_controller_names(slint::ModelRc::from(std::rc::Rc::new( + slint::VecModel::from( + controller_names + .iter() + .map(|x| x.into()) + .collect::>(), + ), + ))); + + let controller_paths = ui::input::get_controller_paths(); + handle.set_controller_paths(slint::ModelRc::from(std::rc::Rc::new( + slint::VecModel::from( + controller_paths + .iter() + .map(|x| x.into()) + .collect::>(), + ), + ))); + + let selected_controllers = slint::VecModel::default(); + for i in 0..4 { + let assigned_path = + if let Some(current_selected_path) = ¤t_selected_paths[i] { + current_selected_path.to_string() + } else if let Some(config_assigned_path) = &controller_assignment[i] { + config_assigned_path.to_string() + } else { + String::new() + }; + let selected_index = controller_paths + .iter() + .position(|controller_path| assigned_path == *controller_path) + .unwrap_or(0) as i32; + selected_controllers.push(selected_index); + } + handle.set_selected_controller(slint::ModelRc::from(std::rc::Rc::new( + selected_controllers, + ))); + }) + .unwrap(); + }); let weak_app = app.as_weak(); app.on_input_profile_button_clicked(move || { @@ -411,7 +415,7 @@ fn controller_window( }); } -pub fn save_settings(app: &AppWindow, controller_paths: &[Option]) { +pub fn save_settings(app: &AppWindow) { let mut config = ui::config::Config::new(); config.video.integer_scaling = app.get_integer_scaling(); config.video.fullscreen = app.get_fullscreen(); @@ -443,8 +447,16 @@ pub fn save_settings(app: &AppWindow, controller_paths: &[Option]) { for (i, selected_controller) in app.get_selected_controller().iter().enumerate() { if app.get_controller_changed().row_data(i).unwrap_or(false) { - config.input.controller_assignment[i] = - controller_paths[selected_controller as usize].clone(); + let controller_path = app + .get_controller_paths() + .row_data(selected_controller as usize) + .unwrap() + .to_string(); + if controller_path.is_empty() { + config.input.controller_assignment[i] = None; + } else { + config.input.controller_assignment[i] = Some(controller_path); + } } } } @@ -493,21 +505,17 @@ pub fn app_window() { let app = AppWindow::new().unwrap(); about_window(&app); ui::retroachievements::ra_window(&app); - let mut controller_paths; { - let game_ui = ui::Ui::new(); - let mut controller_names = ui::input::get_controller_names(&game_ui); - controller_names.insert(0, "None".into()); - controller_paths = ui::input::get_controller_paths(&game_ui); - controller_paths.insert(0, None); - settings_window(&app, &game_ui.config); - controller_window(&app, &game_ui.config, &controller_names, &controller_paths); - local_game_window(&app, &game_ui.config, &controller_paths); + let config = ui::config::Config::new(); + settings_window(&app, &config); + controller_window(&app, &config); + local_game_window(&app, &config); } - ui::netplay::netplay_window(&app, &controller_paths); + ui::netplay::netplay_window(&app); ui::cheats::cheats_window(&app); app.run().unwrap(); - save_settings(&app, &controller_paths); + save_settings(&app); + unsafe { sdl3_sys::init::SDL_Quit() }; } pub fn run_rom( diff --git a/src/ui/gui/appwindow.slint b/src/ui/gui/appwindow.slint index 04cd7bdb..a6ab7afc 100644 --- a/src/ui/gui/appwindow.slint +++ b/src/ui/gui/appwindow.slint @@ -41,6 +41,7 @@ export component AppWindow inherits Window { callback ra_games_clicked; callback ra_show_profile_clicked; callback ra_toggled(bool,bool,bool,bool); + callback controller_window_created; in property version <=> AboutData.version; in property has_update <=> AboutData.has_update; in-out property ra_username <=> RAData.ra_username; @@ -72,10 +73,10 @@ export component AppWindow inherits Window { in-out property selected_profile_binding <=> ControllerData.selected_profile_binding; in-out property input_profiles <=> ControllerData.input_profiles; in-out property controller_names <=> ControllerData.controller_names; + in-out property controller_paths <=> ControllerData.controller_paths; in-out property selected_controller <=> ControllerData.selected_controller; in-out property game_running <=> State.game_running; in-out property recent_roms <=> State.recent_roms; - in-out property blank_profiles <=> ControllerData.blank_profiles; in-out property cheat_game_name <=> CheatsData.cheat_game_name; in-out property cheat_game_crc <=> CheatsData.cheat_game_crc; in-out property cheats <=> CheatsData.cheats; @@ -119,6 +120,9 @@ export component AppWindow inherits Window { transferpak_toggled(player,enabled) => { transferpak_toggled(player,enabled); } + controller_window_created => { + controller_window_created(); + } } if(side-bar.current-item == 2): Netplay { create_session_button_clicked => { diff --git a/src/ui/gui/controller_page.slint b/src/ui/gui/controller_page.slint index 156e10a4..9a0e1a68 100644 --- a/src/ui/gui/controller_page.slint +++ b/src/ui/gui/controller_page.slint @@ -14,16 +14,21 @@ export global ControllerData { in-out property <[int]> selected_profile_binding: [-1, -1, -1, -1]; in-out property <[string]> input_profiles; in-out property <[string]> controller_names; + in-out property <[string]> controller_paths; in-out property <[int]> selected_controller; in-out property <[bool]> controller_changed; - in-out property blank_profiles; } export component ControllerConfig inherits Page { callback input_profile_button_clicked; callback transferpak_toggled(int,bool); + callback controller_window_created; title: @tr("Controller Configuration"); + init => { + controller_window_created(); + } + VerticalBox { alignment: start; HorizontalBox { @@ -92,7 +97,7 @@ export component ControllerConfig inherits Page { } } - if !ControllerData.blank_profiles: GroupBox { + GroupBox { title: @tr("Profile"); horizontal-stretch: 0.25; VerticalLayout { diff --git a/src/ui/input.rs b/src/ui/input.rs index 76afe03a..23bd1fca 100644 --- a/src/ui/input.rs +++ b/src/ui/input.rs @@ -341,10 +341,10 @@ fn hotkey_pressed( pressed } -pub fn get_controller_names(game_ui: &ui::Ui) -> Vec { +pub fn get_controller_names() -> Vec { let mut controllers: Vec = vec![]; - for joystick in game_ui.input.joysticks.iter() { + for joystick in get_joysticks().iter() { let name = unsafe { sdl3_sys::joystick::SDL_GetJoystickNameForID(*joystick) }; controllers.push(if name.is_null() { "Unknown controller".to_string() @@ -352,22 +352,24 @@ pub fn get_controller_names(game_ui: &ui::Ui) -> Vec { unsafe { std::ffi::CStr::from_ptr(name).to_str().unwrap() }.to_string() }); } + controllers.insert(0, "None".into()); controllers } #[cfg(feature = "gui")] -pub fn get_controller_paths(game_ui: &ui::Ui) -> Vec> { - let mut controller_paths: Vec> = vec![]; +pub fn get_controller_paths() -> Vec { + let mut controller_paths: Vec = vec![]; - for joystick in game_ui.input.joysticks.iter() { + for joystick in get_joysticks().iter() { let path = unsafe { sdl3_sys::joystick::SDL_GetJoystickPathForID(*joystick) }; controller_paths.push(if path.is_null() { - None + String::new() } else { - Some(unsafe { std::ffi::CStr::from_ptr(path).to_str().unwrap() }.to_string()) + unsafe { std::ffi::CStr::from_ptr(path).to_str().unwrap() }.to_string() }); } + controller_paths.insert(0, String::new()); controller_paths } @@ -553,13 +555,15 @@ pub fn get(ui: &mut ui::Ui, channel: usize) -> InputData { } } -pub fn assign_controller(ui: &mut ui::Ui, controller: i32, port: usize) { - if controller < ui.input.joysticks.len() as i32 { - let path = unsafe { - sdl3_sys::joystick::SDL_GetJoystickPathForID(ui.input.joysticks[controller as usize]) - }; +pub fn assign_controller(config: &mut ui::config::Config, controller: i32, port: usize) { + let joysticks = get_joysticks(); + if controller < 0 { + config.input.controller_assignment[port - 1] = None; + } else if controller < joysticks.len() as i32 { + let path = + unsafe { sdl3_sys::joystick::SDL_GetJoystickPathForID(joysticks[controller as usize]) }; if !path.is_null() { - ui.config.input.controller_assignment[port - 1] = + config.input.controller_assignment[port - 1] = Some(unsafe { std::ffi::CStr::from_ptr(path).to_str().unwrap().to_string() }); } else { eprintln!("Invalid controller path for controller {controller}"); @@ -569,18 +573,18 @@ pub fn assign_controller(ui: &mut ui::Ui, controller: i32, port: usize) { } } -pub fn bind_input_profile(ui: &mut ui::Ui, profile: String, port: usize) { - if ui.config.input.input_profiles.contains_key(&profile) { - ui.config.input.input_profile_binding[port - 1] = profile; +pub fn bind_input_profile(config: &mut ui::config::Config, profile: String, port: usize) { + if config.input.input_profiles.contains_key(&profile) { + config.input.input_profile_binding[port - 1] = profile; } else { eprintln!("Invalid profile name") } } -pub fn clear_bindings(ui: &mut ui::Ui) { +pub fn clear_bindings(config: &mut ui::config::Config) { for i in 0..4 { - ui.config.input.controller_assignment[i] = None; - ui.config.input.input_profile_binding[i] = "default".to_string(); + config.input.controller_assignment[i] = None; + config.input.input_profile_binding[i] = "default".to_string(); } } @@ -604,10 +608,17 @@ fn close_input_profile_window( sdl3_ttf_sys::ttf::TTF_DestroyRendererTextEngine(text_engine); sdl3_sys::render::SDL_DestroyRenderer(renderer); sdl3_sys::video::SDL_DestroyWindow(window); + sdl3_ttf_sys::ttf::TTF_Quit(); + sdl3_sys::init::SDL_Quit(); } } -pub fn configure_input_profile(ui: &mut ui::Ui, profile: String, dinput: bool, deadzone: i32) { +pub fn configure_input_profile( + config: &mut ui::config::Config, + profile: String, + dinput: bool, + deadzone: i32, +) { ui::sdl_init(sdl3_sys::init::SDL_INIT_VIDEO); ui::ttf_init(); @@ -622,7 +633,7 @@ pub fn configure_input_profile(ui: &mut ui::Ui, profile: String, dinput: bool, d let mut open_joysticks: Vec<*mut sdl3_sys::joystick::SDL_Joystick> = Vec::new(); let mut open_controllers: Vec<*mut sdl3_sys::gamepad::SDL_Gamepad> = Vec::new(); - for joystick in ui.input.joysticks.iter() { + for joystick in get_joysticks().iter() { if !dinput { let controller = unsafe { sdl3_sys::gamepad::SDL_OpenGamepad(*joystick) }; if !controller.is_null() { @@ -847,7 +858,7 @@ pub fn configure_input_profile(ui: &mut ui::Ui, profile: String, dinput: bool, d dinput, deadzone, }; - ui.config.input.input_profiles.insert(profile, new_profile); + config.input.input_profiles.insert(profile, new_profile); } pub fn get_default_profile() -> ui::config::InputProfile { @@ -1050,6 +1061,22 @@ pub fn get_default_profile() -> ui::config::InputProfile { } } +fn get_joysticks() -> Vec { + ui::sdl_init(sdl3_sys::init::SDL_INIT_GAMEPAD); + unsafe { sdl3_sys::events::SDL_PumpEvents() }; + let mut num_joysticks = 0; + let sdl_joysticks = unsafe { sdl3_sys::joystick::SDL_GetJoysticks(&mut num_joysticks) }; + if !sdl_joysticks.is_null() { + let parts = + unsafe { std::slice::from_raw_parts(sdl_joysticks, num_joysticks as usize) }.to_vec(); + unsafe { sdl3_sys::stdinc::SDL_free(sdl_joysticks as *mut std::ffi::c_void) }; + parts + } else { + eprintln!("Could not get joysticks"); + vec![] + } +} + pub fn init(ui: &mut ui::Ui) { ui.input.keyboard_state = unsafe { sdl3_sys::keyboard::SDL_GetKeyboardState(std::ptr::null_mut()) }; @@ -1063,7 +1090,7 @@ pub fn init(ui: &mut ui::Ui) { { let mut joystick_id = sdl3_sys::everything::SDL_JoystickID(0); - for joystick in ui.input.joysticks.iter() { + for joystick in get_joysticks().iter() { let path = unsafe { sdl3_sys::joystick::SDL_GetJoystickPathForID(*joystick) }; if !path.is_null() && unsafe { std::ffi::CStr::from_ptr(path).to_str().unwrap() } diff --git a/src/ui/netplay.rs b/src/ui/netplay.rs index 006e6ab3..889c7a7a 100644 --- a/src/ui/netplay.rs +++ b/src/ui/netplay.rs @@ -1208,17 +1208,15 @@ pub fn setup_join_window( join_window.show().unwrap(); } -pub fn netplay_window(app: &AppWindow, controller_paths: &[Option]) { +pub fn netplay_window(app: &AppWindow) { let weak_create = app.as_weak(); let weak_app = app.as_weak(); - let controller_paths_create = controller_paths.to_owned(); app.on_create_session_button_clicked(move || { - let controller_paths = controller_paths_create.clone(); let weak_app = weak_app.clone(); weak_create .upgrade_in_event_loop(move |handle| { let create_window = NetplayCreate::new().unwrap(); - save_settings(&handle, &controller_paths); + save_settings(&handle); setup_create_window( &create_window, ui::GameSettings { @@ -1242,14 +1240,12 @@ pub fn netplay_window(app: &AppWindow, controller_paths: &[Option]) { let weak_join = app.as_weak(); let weak_app = app.as_weak(); - let controller_paths_join = controller_paths.to_owned(); app.on_join_session_button_clicked(move || { - let controller_paths = controller_paths_join.clone(); let weak_app = weak_app.clone(); weak_join .upgrade_in_event_loop(move |handle| { let join_window = NetplayJoin::new().unwrap(); - save_settings(&handle, &controller_paths); + save_settings(&handle); setup_join_window( &join_window, handle.get_rom_dir(), diff --git a/src/ui/video.rs b/src/ui/video.rs index 2bd53867..b8f0eb31 100644 --- a/src/ui/video.rs +++ b/src/ui/video.rs @@ -150,6 +150,8 @@ pub fn close(ui: &ui::Ui) { unsafe { rdp_close(); sdl3_sys::video::SDL_DestroyWindow(ui.video.window); + sdl3_ttf_sys::ttf::TTF_Quit(); + sdl3_sys::init::SDL_Quit(); } }