From 99566f8a96d5c60252853ef6f641003229345c36 Mon Sep 17 00:00:00 2001 From: Kamil Jarosz Date: Thu, 8 Aug 2024 01:41:34 +0200 Subject: [PATCH] desktop: Make file pickers asynchronous This patch fixes the problem of Ruffle not responding when picking a file. --- desktop/src/app.rs | 17 ++++++++++------- desktop/src/gui/widgets.rs | 11 +++++++---- desktop/src/util.rs | 28 ++++------------------------ 3 files changed, 21 insertions(+), 35 deletions(-) diff --git a/desktop/src/app.rs b/desktop/src/app.rs index 754cc10631ccc..4c022f1d857ef 100644 --- a/desktop/src/app.rs +++ b/desktop/src/app.rs @@ -136,6 +136,7 @@ impl App { // Poll UI events. let event_loop = self.event_loop.take().expect("App already running"); + let event_loop_proxy = event_loop.create_proxy(); event_loop.run(move |event, elwt| { let mut check_redraw = false; match event { @@ -514,13 +515,15 @@ impl App { } winit::event::Event::UserEvent(RuffleEvent::BrowseAndOpen(options)) => { - if let Some(url) = - pick_file(false, None).and_then(|p| Url::from_file_path(p).ok()) - { - self.gui - .borrow_mut() - .create_movie(&mut self.player, *options, url); - } + let event_loop = event_loop_proxy.clone(); + tokio::spawn(async move { + if let Some(url) = pick_file(None) + .await + .and_then(|p| Url::from_file_path(p).ok()) + { + let _ = event_loop.send_event(RuffleEvent::OpenURL(url, options)); + } + }); } winit::event::Event::UserEvent(RuffleEvent::OpenURL(url, options)) => { diff --git a/desktop/src/gui/widgets.rs b/desktop/src/gui/widgets.rs index f6f45583845e4..b33951b34c928 100644 --- a/desktop/src/gui/widgets.rs +++ b/desktop/src/gui/widgets.rs @@ -56,10 +56,13 @@ impl PathOrUrlField { path }); - if let Some(path) = pick_file(true, dir) { - let mut value_lock = Self::lock_value(&self.value); - *value_lock = path.to_string_lossy().to_string(); - } + let value = self.value.clone(); + tokio::spawn(async move { + if let Some(path) = pick_file(dir).await { + let mut value_lock = Self::lock_value(&value); + *value_lock = path.to_string_lossy().to_string(); + } + }); } let mut value_locked = Self::lock_value(&self.value); diff --git a/desktop/src/util.rs b/desktop/src/util.rs index 47bf0eb67ada1..d3730d5e5d696 100644 --- a/desktop/src/util.rs +++ b/desktop/src/util.rs @@ -1,7 +1,7 @@ use crate::custom_event::RuffleEvent; use anyhow::{anyhow, Error}; use gilrs::Button; -use rfd::FileDialog; +use rfd::AsyncFileDialog; use ruffle_core::events::{GamepadButton, KeyCode, TextControlCode}; use std::path::{Path, PathBuf}; use url::Url; @@ -244,8 +244,8 @@ pub fn parse_url(path: &Path) -> Result { } } -fn actually_pick_file(dir: Option) -> Option { - let mut dialog = FileDialog::new() +pub async fn pick_file(dir: Option) -> Option { + let mut dialog = AsyncFileDialog::new() .add_filter("Flash Files", &["swf", "spl", "ruf"]) .add_filter("All Files", &["*"]) .set_title("Load a Flash File"); @@ -254,27 +254,7 @@ fn actually_pick_file(dir: Option) -> Option { dialog = dialog.set_directory(dir); } - dialog.pick_file() -} - -// [NA] Horrible hacky workaround for https://github.com/rust-windowing/winit/issues/2291 -// We only need the workaround from within UI code, not when executing custom events -// The workaround causes Ruffle to show as "not responding" on windows, so we don't use it if we don't need to -#[cfg(windows)] -pub fn pick_file(in_ui: bool, path: Option) -> Option { - if in_ui { - std::thread::spawn(move || actually_pick_file(path)) - .join() - .ok() - .flatten() - } else { - actually_pick_file(path) - } -} - -#[cfg(not(windows))] -pub fn pick_file(_in_ui: bool, path: Option) -> Option { - actually_pick_file(path) + dialog.pick_file().await.map(|h| h.into()) } #[cfg(not(feature = "tracy"))]