Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Makes open_file and open_dir fallible #1282

Merged
merged 1 commit into from
Feb 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions gui/src/setup/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,13 @@ async fn get_dumper(win: SetupWizard) {
async fn browse_data_root(win: SetupWizard) {
// Ask the user to browse for a directory.
let path = match open_dir(&win, "Data location").await {
Some(v) => v,
None => return,
Ok(Some(v)) => v,
Ok(None) => return,
Err(e) => {
let m = slint::format!("Failed to browse for data location: {}.", e.display());
error(Some(&win), m).await;
return;
}
};

// Allow only valid unicode path.
Expand Down Expand Up @@ -196,8 +201,13 @@ async fn set_data_root(win: SetupWizard) {
async fn browse_firmware(win: SetupWizard) {
// Ask the user to browse for a file.
let path = match open_file(&win, "Select a firmware dump", FileType::Firmware).await {
Some(v) => v,
None => return,
Ok(Some(v)) => v,
Ok(None) => return,
Err(e) => {
let m = slint::format!("Failed to browse for a firmware dump: {}.", e.display());
error(Some(&win), m).await;
return;
}
};

// Allow only valid unicode path.
Expand Down
14 changes: 5 additions & 9 deletions gui/src/ui/backend/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#[cfg(target_os = "linux")]
pub(super) use self::wayland::*;
pub(super) use self::window::Window;
pub(super) use self::window::*;

use i_slint_core::graphics::RequestedGraphicsAPI;
use i_slint_renderer_skia::SkiaRenderer;
Expand All @@ -25,7 +25,7 @@ use winit::window::WindowId;
mod wayland;
mod window;

/// Back-end for Slint to run on top of winit event loop.
/// Back-end for Slint to run on top of [`wae`].
///
/// The following are caveats of this back-end:
///
Expand All @@ -35,7 +35,7 @@ mod window;
pub struct SlintBackend {
#[cfg(target_os = "linux")]
wayland: Option<Wayland>,
windows: RefCell<FxHashMap<WindowId, Weak<Window>>>,
windows: RefCell<FxHashMap<WindowId, Weak<SlintWindow>>>,
}

impl SlintBackend {
Expand Down Expand Up @@ -159,8 +159,8 @@ impl slint::platform::Platform for Platform {
})));

// Just panic if people try to create the window when the event loop already exited.
let win = Rc::<Window>::new_cyclic(move |weak| {
Window::new(win, slint::Window::new(weak.clone()), renderer)
let win = Rc::<SlintWindow>::new_cyclic(move |weak| {
SlintWindow::new(win, slint::Window::new(weak.clone()), renderer)
});

assert!(self
Expand All @@ -185,10 +185,6 @@ pub enum BackendError {
#[error("couldn't get global objects from Wayland compositor")]
RetrieveWaylandGlobals(#[source] wayland_client::globals::GlobalError),

#[cfg(target_os = "linux")]
#[error("couldn't bind xdg_wm_base")]
BindXdgWmBase(#[source] wayland_client::globals::BindError),

#[cfg(target_os = "linux")]
#[error("couldn't bind xdg_wm_dialog_v1")]
BindXdgWmDialogV1(#[source] wayland_client::globals::BindError),
Expand Down
25 changes: 6 additions & 19 deletions gui/src/ui/backend/wayland.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use wayland_protocols::xdg::shell::client::xdg_wm_base::XdgWmBase;
pub struct Wayland {
queue: RefCell<EventQueue<WaylandState>>,
state: RefCell<WaylandState>,
conn: Connection,
connection: Connection,
}

impl Wayland {
Expand All @@ -29,27 +29,18 @@ impl Wayland {
pub unsafe fn new(display: WaylandDisplayHandle) -> Result<Self, BackendError> {
// Get wayland connection.
let backend = Backend::from_foreign_display(display.display.as_ptr().cast());
let conn = Connection::from_backend(backend);
let connection = Connection::from_backend(backend);

// Get global objects.
let (globals, mut queue) = registry_queue_init::<WaylandState>(&conn)
let (globals, mut queue) = registry_queue_init::<WaylandState>(&connection)
.map_err(BackendError::RetrieveWaylandGlobals)?;
let qh = queue.handle();

// Get xdg_wm_base.
let v = XdgWmBase::interface().version;
let xdg_base: XdgWmBase = globals
.bind(&qh, v..=v, ())
.map_err(BackendError::BindXdgWmBase)?;

// Get xdg_wm_dialog_v1.
let v = XdgWmDialogV1::interface().version;
let xdg_dialog: XdgWmDialogV1 = match globals.bind(&qh, v..=v, ()) {
Ok(v) => v,
Err(e) => {
xdg_base.destroy();
return Err(BackendError::BindXdgWmDialogV1(e));
}
Err(e) => return Err(BackendError::BindXdgWmDialogV1(e)),
};

// Get zxdg_exporter_v2.
Expand All @@ -58,7 +49,6 @@ impl Wayland {
Ok(v) => v,
Err(e) => {
xdg_dialog.destroy();
xdg_base.destroy();
return Err(BackendError::BindZxdgExporterV2(e));
}
};
Expand All @@ -67,7 +57,6 @@ impl Wayland {
let mut state = WaylandState {
xdg_exporter,
xdg_dialog,
xdg_base,
};

queue
Expand All @@ -77,7 +66,7 @@ impl Wayland {
Ok(Self {
queue: RefCell::new(queue),
state: RefCell::new(state),
conn,
connection,
})
}

Expand All @@ -90,7 +79,7 @@ impl Wayland {
}

pub fn connection(&self) -> &Connection {
&self.conn
&self.connection
}

pub fn run(&self) -> impl Future<Output = ()> + '_ {
Expand All @@ -102,7 +91,6 @@ impl Wayland {
pub struct WaylandState {
xdg_exporter: ZxdgExporterV2,
xdg_dialog: XdgWmDialogV1,
xdg_base: XdgWmBase,
}

impl WaylandState {
Expand All @@ -119,7 +107,6 @@ impl Drop for WaylandState {
fn drop(&mut self) {
self.xdg_exporter.destroy();
self.xdg_dialog.destroy();
self.xdg_base.destroy();
}
}

Expand Down
14 changes: 7 additions & 7 deletions gui/src/ui/backend/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ use wae::{Signal, WindowHandler, WinitWindow};
use winit::event::{DeviceId, ElementState, InnerSizeWriter, MouseButton};
use winit::window::WindowId;

/// Implementation of [`WindowAdapter`].
pub struct Window {
/// Implementation of [`slint::platform::WindowAdapter`].
pub struct SlintWindow {
winit: Rc<winit::window::Window>,
slint: slint::Window,
renderer: SkiaRenderer,
Expand All @@ -30,7 +30,7 @@ pub struct Window {
preferred_size: Cell<Option<winit::dpi::PhysicalSize<u32>>>,
}

impl Window {
impl SlintWindow {
pub fn new(
winit: Rc<winit::window::Window>,
slint: slint::Window,
Expand Down Expand Up @@ -68,13 +68,13 @@ impl Window {
}
}

impl WinitWindow for Window {
impl WinitWindow for SlintWindow {
fn id(&self) -> WindowId {
self.winit.id()
}
}

impl WindowHandler for Window {
impl WindowHandler for SlintWindow {
fn on_resized(
&self,
new: winit::dpi::PhysicalSize<u32>,
Expand Down Expand Up @@ -260,7 +260,7 @@ impl WindowHandler for Window {
}
}

impl WindowAdapter for Window {
impl WindowAdapter for SlintWindow {
fn window(&self) -> &slint::Window {
&self.slint
}
Expand Down Expand Up @@ -366,7 +366,7 @@ impl WindowAdapter for Window {
}
}

impl WindowAdapterInternal for Window {
impl WindowAdapterInternal for SlintWindow {
fn as_any(&self) -> &dyn Any {
self
}
Expand Down
16 changes: 10 additions & 6 deletions gui/src/ui/linux/dialogs.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use super::PlatformError;
use crate::ui::{DesktopWindow, FileType, SlintBackend};
use ashpd::desktop::file_chooser::{FileFilter, SelectedFiles};
use ashpd::desktop::ResponseError;
Expand All @@ -14,7 +15,7 @@ pub async fn open_file<T: DesktopWindow>(
parent: &T,
title: impl AsRef<str>,
ty: FileType,
) -> Option<PathBuf> {
) -> Result<Option<PathBuf>, PlatformError> {
// Build filter.
let filter = match ty {
FileType::Firmware => FileFilter::new("Firmware Dump").glob("*.obf"),
Expand All @@ -37,15 +38,18 @@ pub async fn open_file<T: DesktopWindow>(
// Get response.
let resp = match req.unwrap().response() {
Ok(v) => v,
Err(ashpd::Error::Response(ResponseError::Cancelled)) => return None,
Err(ashpd::Error::Response(ResponseError::Cancelled)) => return Ok(None),
Err(_) => unimplemented!(),
};

// Get file path.
Some(resp.uris().first().unwrap().to_file_path().unwrap())
Ok(Some(resp.uris().first().unwrap().to_file_path().unwrap()))
}

pub async fn open_dir<T: DesktopWindow>(parent: &T, title: impl AsRef<str>) -> Option<PathBuf> {
pub async fn open_dir<T: DesktopWindow>(
parent: &T,
title: impl AsRef<str>,
) -> Result<Option<PathBuf>, PlatformError> {
// Send the request
let parent = get_parent_id(parent);
let req = SelectedFiles::open_file()
Expand All @@ -63,12 +67,12 @@ pub async fn open_dir<T: DesktopWindow>(parent: &T, title: impl AsRef<str>) -> O
// Get response.
let resp = match req.unwrap().response() {
Ok(v) => v,
Err(ashpd::Error::Response(ResponseError::Cancelled)) => return None,
Err(ashpd::Error::Response(ResponseError::Cancelled)) => return Ok(None),
Err(_) => unimplemented!(),
};

// Get directory path.
Some(resp.uris().first().unwrap().to_file_path().unwrap())
Ok(Some(resp.uris().first().unwrap().to_file_path().unwrap()))
}

fn get_parent_id<P>(parent: &P) -> Parent
Expand Down
10 changes: 7 additions & 3 deletions gui/src/ui/macos/dialogs.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::view::get_window;
use super::PlatformError;
use crate::ui::{DesktopWindow, FileType};
use block2::RcBlock;
use futures::StreamExt;
Expand All @@ -18,11 +19,14 @@ pub async fn open_file<T: DesktopWindow>(
parent: &T,
title: impl AsRef<str>,
ty: FileType,
) -> Option<PathBuf> {
) -> Result<Option<PathBuf>, PlatformError> {
todo!();
}

pub async fn open_dir<T: DesktopWindow>(parent: &T, title: impl AsRef<str>) -> Option<PathBuf> {
pub async fn open_dir<T: DesktopWindow>(
parent: &T,
title: impl AsRef<str>,
) -> Result<Option<PathBuf>, PlatformError> {
// Create NSOpenPanel.
let title = NSString::from_str(title.as_ref());
let panel: *mut NSObject = unsafe { msg_send![class!(NSOpenPanel), openPanel] };
Expand Down Expand Up @@ -55,5 +59,5 @@ pub async fn open_dir<T: DesktopWindow>(parent: &T, title: impl AsRef<str>) -> O
unsafe { msg_send![panel, beginSheetModalForWindow:parent completionHandler:cb.deref()] };

// The beginSheetModalForWindow will return immediately so we need a channel here.
rx.next().await.flatten()
Ok(rx.next().await.flatten())
}
6 changes: 3 additions & 3 deletions gui/src/ui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ impl<T: ComponentHandle + WinitWindow> DesktopWindow for T {
use winit::platform::wayland::WindowExtWayland;

let win = WindowInner::from_pub(self.window()).window_adapter();
let win = Window::from_adapter(win.as_ref());
let win = SlintWindow::from_adapter(win.as_ref());

win.winit().xdg_toplevel()
}
Expand Down Expand Up @@ -100,7 +100,7 @@ pub trait RuntimeExt: ComponentHandle {
impl<T: ComponentHandle> RuntimeExt for T {
async fn wait(&self) {
let win = WindowInner::from_pub(self.window()).window_adapter();
let win = Window::from_adapter(win.as_ref());
let win = SlintWindow::from_adapter(win.as_ref());

win.hidden().wait().await;
}
Expand All @@ -119,7 +119,7 @@ macro_rules! impl_wae {
impl WinitWindow for $ty {
fn id(&self) -> WindowId {
let win = WindowInner::from_pub(self.window()).window_adapter();
let win = Window::from_adapter(win.as_ref());
let win = SlintWindow::from_adapter(win.as_ref());

win.id()
}
Expand Down
Loading