Skip to content

Commit

Permalink
Initializes async executor (#1177)
Browse files Browse the repository at this point in the history
  • Loading branch information
ultimaweapon authored Dec 11, 2024
1 parent 2a6aa24 commit a000119
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 78 deletions.
29 changes: 29 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion gui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ bitfield-struct = "0.9.2"
ciborium = "0.2.2"
clap = { version = "4.5.21", features = ["derive"] }
erdp = "0.1.1"
futures = "0.3.31"
gdbstub = "0.7.3"
gdbstub_arch = "0.3.1"
humansize = "2.1.3"
i-slint-renderer-skia = "=1.8.0"
i-slint-renderer-skia = { version = "=1.8.0", features = ["wayland", "x11"] }
libc = "0.2.164"
num_enum = "0.7.3"
obconf = { path = "../src/obconf", features = ["serde", "virt"] }
Expand Down
11 changes: 0 additions & 11 deletions gui/main_window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,12 @@ MainWindow::MainWindow() :

// Help menu.
auto helpMenu = menuBar()->addMenu("&Help");
auto reportIssue = new QAction("&Report Issue", this);
auto aboutQt = new QAction("About &Qt", this);
auto about = new QAction("&About Obliteration", this);

connect(reportIssue, &QAction::triggered, this, &MainWindow::reportIssue);
connect(aboutQt, &QAction::triggered, &QApplication::aboutQt);
connect(about, &QAction::triggered, this, &MainWindow::aboutObliteration);

helpMenu->addAction(reportIssue);
helpMenu->addSeparator();
helpMenu->addAction(aboutQt);
helpMenu->addAction(about);

Expand All @@ -59,13 +55,6 @@ MainWindow::~MainWindow()
{
}

void MainWindow::reportIssue()
{
if (!QDesktopServices::openUrl(QUrl("https://github.com/obhq/obliteration/issues/new"))) {
QMessageBox::critical(this, "Error", "Failed to open https://github.com/obhq/obliteration/issues/new.");
}
}

void MainWindow::aboutObliteration()
{
QMessageBox::about(
Expand Down
1 change: 0 additions & 1 deletion gui/main_window.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ class MainWindow final : public QMainWindow {
MainWindow();
~MainWindow() override;
private slots:
void reportIssue();
void aboutObliteration();
private:
QStackedWidget *m_main;
Expand Down
95 changes: 30 additions & 65 deletions gui/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use self::data::{DataError, DataMgr};
use self::graphics::{Graphics, GraphicsError, PhysicalDevice};
use self::profile::Profile;
use self::setup::{run_setup, SetupError};
use self::ui::{ErrorWindow, MainWindow, ProfileModel, ResolutionModel, SlintBackend};
use self::ui::{ErrorWindow, MainWindow, ProfileModel, ResolutionModel, RuntimeExt, SlintBackend};
use clap::{Parser, ValueEnum};
use debug::DebugServer;
use erdp::ErrorDisplay;
Expand All @@ -16,10 +16,6 @@ use std::process::ExitCode;
use std::rc::Rc;
use std::sync::Arc;
use thiserror::Error;
use winit::application::ApplicationHandler;
use winit::event::WindowEvent;
use winit::event_loop::{ActiveEventLoop, EventLoop};
use winit::window::WindowId;

mod data;
mod debug;
Expand All @@ -30,6 +26,7 @@ mod panic;
mod profile;
#[cfg(unix)]
mod rlim;
mod rt;
mod setup;
mod ui;
mod vfs;
Expand Down Expand Up @@ -76,33 +73,44 @@ fn main() -> ExitCode {
return ExitCode::FAILURE;
}

// Setup UI event loop.
let mut el = EventLoop::<ProgramEvent>::with_user_event();
let el = match el.build() {
Ok(v) => v,
Err(e) => {
error(format!(
"Failed to create winit event loop: {}.",
e.display()
));
// Run.
let run = async move {
// Setup Slint back-end. This need to be done before using any Slint API.
slint::platform::set_platform(Box::new(SlintBackend::new())).unwrap();

return ExitCode::FAILURE;
}
};
// Run.
let e = match run(args, exe).await {
Ok(_) => return,
Err(e) => e,
};

// Run.
let mut prog = Program { args };
// Show error window.
let win = ErrorWindow::new().unwrap();

win.set_message(format!("An unexpected error has occurred: {}.", e.display()).into());
win.on_close({
let win = win.as_weak();

move || win.unwrap().hide().unwrap()
});

match el.run_app(&mut prog) {
win.exec().await.unwrap();
};

match self::rt::block_on(run) {
Ok(_) => ExitCode::SUCCESS,
Err(e) => {
error(format!("Failed to run winit event loop: {}.", e.display()));
error(format!(
"Failed to run application runtime: {}.",
e.display()
));

ExitCode::FAILURE
}
}
}

fn run_vmm(args: &ProgramArgs, exe: &PathBuf) -> Result<(), ProgramError> {
async fn run(args: ProgramArgs, exe: PathBuf) -> Result<(), ProgramError> {
#[cfg(unix)]
rlim::set_rlimit_nofile().map_err(ProgramError::FdLimit)?;

Expand Down Expand Up @@ -316,49 +324,6 @@ fn run_launcher(
Ok(Some((profile, exit)))
}

/// Implementation of [`ApplicationHandler`] for main program mode.
struct Program {
args: ProgramArgs,
}

impl Program {
async fn error(&self, msg: impl Into<SharedString>) {
// Show error window.
let win = ErrorWindow::new().unwrap();

win.set_message(msg.into());
win.on_close({
let win = win.as_weak();

move || win.unwrap().hide().unwrap()
});

win.show();

todo!()
}
}

impl ApplicationHandler<ProgramEvent> for Program {
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
slint::platform::set_platform(Box::new(SlintBackend::new())).unwrap();

todo!()
}

fn window_event(
&mut self,
event_loop: &ActiveEventLoop,
window_id: WindowId,
event: WindowEvent,
) {
todo!()
}
}

/// Event to wakeup UI event loop.
enum ProgramEvent {}

/// Program arguments parsed from command line.
#[derive(Parser)]
#[command(about = None)]
Expand Down
58 changes: 58 additions & 0 deletions gui/src/rt/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
use futures::executor::LocalPool;
use futures::task::LocalSpawnExt;
use std::future::Future;
use thiserror::Error;
use winit::application::ApplicationHandler;
use winit::error::EventLoopError;
use winit::event::WindowEvent;
use winit::event_loop::{ActiveEventLoop, EventLoop};
use winit::window::WindowId;

pub fn block_on(main: impl Future<Output = ()> + 'static) -> Result<(), RuntimeError> {
// Setup winit event loop.
let mut el = EventLoop::<Event>::with_user_event();
let el = el.build().map_err(RuntimeError::CreateEventLoop)?;
let exe = LocalPool::new();

exe.spawner()
.spawn_local(async move {
main.await;
todo!()
})
.unwrap();

// Run event loop.
el.run_app(&mut AsyncExecutor(exe))
.map_err(RuntimeError::RunEventLoop)
}

/// Implementation of [`ApplicationHandler`] to drive [`Future`].
struct AsyncExecutor(LocalPool);

impl ApplicationHandler<Event> for AsyncExecutor {
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
self.0.run_until_stalled();
}

fn window_event(
&mut self,
event_loop: &ActiveEventLoop,
window_id: WindowId,
event: WindowEvent,
) {
todo!()
}
}

/// Event to wakeup winit event loop.
enum Event {}

/// Represents an error when [`block_on()`] fails.
#[derive(Debug, Error)]
pub enum RuntimeError {
#[error("couldn't create event loop")]
CreateEventLoop(#[source] EventLoopError),

#[error("couldn't run event loop")]
RunEventLoop(#[source] EventLoopError),
}
13 changes: 13 additions & 0 deletions gui/src/ui/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
pub use self::backend::*;
pub use self::profile::*;

use slint::ComponentHandle;

mod backend;
mod profile;

/// Provides methods for [`ComponentHandle`] to work with our async runtime.
pub trait RuntimeExt: ComponentHandle {
async fn exec(&self) -> Result<(), slint::PlatformError>;
}

impl<T: ComponentHandle> RuntimeExt for T {
async fn exec(&self) -> Result<(), slint::PlatformError> {
todo!()
}
}

// This macro includes the generated Rust code from .slint files
slint::include_modules!();

0 comments on commit a000119

Please sign in to comment.