Skip to content

Commit

Permalink
Initializes custom back-end for Slint (#1176)
Browse files Browse the repository at this point in the history
  • Loading branch information
ultimaweapon authored Dec 10, 2024
1 parent a45c697 commit 2a6aa24
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 119 deletions.
13 changes: 7 additions & 6 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 @@ -15,6 +15,7 @@ erdp = "0.1.1"
gdbstub = "0.7.3"
gdbstub_arch = "0.3.1"
humansize = "2.1.3"
i-slint-renderer-skia = "=1.8.0"
libc = "0.2.164"
num_enum = "0.7.3"
obconf = { path = "../src/obconf", features = ["serde", "virt"] }
Expand All @@ -32,7 +33,7 @@ rev = "64787fdc0489724f0914356d925be014a2f1bf3e"
features = ["read"]

[dependencies.slint]
version = "1.8.0"
version = "=1.8.0"
features = [
"backend-winit",
"compat-1-2",
Expand Down
12 changes: 0 additions & 12 deletions gui/main_window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,3 @@ void MainWindow::aboutObliteration()
"PC. This will allows you to play your games forever even if your PlayStation 4 stopped "
"working in the future.");
}

void MainWindow::waitKernelExit(bool success)
{
if (!success) {
QMessageBox::critical(
this,
"Error",
"The kernel was stopped unexpectedly. See the kernel logs for more details.");
}

m_main->setCurrentIndex(0);
}
2 changes: 0 additions & 2 deletions gui/main_window.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,5 @@ private slots:
void reportIssue();
void aboutObliteration();
private:
void waitKernelExit(bool success);

QStackedWidget *m_main;
};
187 changes: 105 additions & 82 deletions gui/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
#![windows_subsystem = "windows"]

use self::data::{DataError, DataMgr};
use self::graphics::{Graphics, GraphicsError, PhysicalDevice, Screen};
use self::graphics::{Graphics, GraphicsError, PhysicalDevice};
use self::profile::Profile;
use self::setup::{run_setup, SetupError};
use self::ui::{ErrorWindow, MainWindow, ProfileModel, ResolutionModel};
use self::vmm::{Vmm, VmmArgs, VmmError, VmmEvent};
use self::ui::{ErrorWindow, MainWindow, ProfileModel, ResolutionModel, SlintBackend};
use clap::{Parser, ValueEnum};
use debug::DebugServer;
use erdp::ErrorDisplay;
use slint::{ComponentHandle, ModelRc, SharedString, VecModel};
use std::cell::Cell;
use std::error::Error;
use std::net::SocketAddrV4;
use std::path::PathBuf;
use std::process::ExitCode;
use std::rc::Rc;
use std::sync::Arc;
use thiserror::Error;
use winit::error::EventLoopError;
use winit::event_loop::EventLoop;
use winit::application::ApplicationHandler;
use winit::event::WindowEvent;
use winit::event_loop::{ActiveEventLoop, EventLoop};
use winit::window::WindowId;

mod data;
mod debug;
Expand All @@ -35,53 +36,73 @@ mod vfs;
mod vmm;

fn main() -> ExitCode {
use std::fmt::Write;

// Check program mode.
let args = ProgramArgs::parse();
let r = match &args.mode {
Some(ProgramMode::PanicHandler) => self::panic::run_handler(),
None => run_vmm(&args),
};

// Check program result.
let e = match r {
Ok(_) => return ExitCode::SUCCESS,
Err(e) => e,
};

// Get full message.
let mut msg = e.to_string();
let mut src = e.source();
match &args.mode {
Some(ProgramMode::PanicHandler) => return self::panic::run_handler(),
None => {}
}

while let Some(e) = src {
write!(msg, " -> {e}").unwrap();
src = e.source();
#[cfg(target_os = "windows")]
fn error(msg: impl AsRef<str>) {
todo!()
}

// Show error window.
let win = ErrorWindow::new().unwrap();
#[cfg(not(target_os = "windows"))]
fn error(msg: impl AsRef<str>) {
eprintln!("{}", msg.as_ref());
}

win.set_message(format!("An unexpected error has occurred: {msg}.").into());
win.on_close({
let win = win.as_weak();
// Spawn panic handler.
let exe = match std::env::current_exe().and_then(std::fs::canonicalize) {
Ok(v) => v,
Err(e) => {
error(format!(
"Failed to get application executable path: {}.",
e.display()
));

return ExitCode::FAILURE;
}
};

move || win.unwrap().hide().unwrap()
});
if let Err(e) = self::panic::spawn_handler(&exe) {
error(format!(
"Failed to spawn panic handler process: {}.",
e.display()
));

win.run().unwrap();
return ExitCode::FAILURE;
}

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()
));

return ExitCode::FAILURE;
}
};

fn run_vmm(args: &ProgramArgs) -> Result<(), ProgramError> {
// Spawn panic handler.
let exe = std::env::current_exe()
.and_then(std::fs::canonicalize)
.map_err(ProgramError::GetCurrentExePath)?;
// Run.
let mut prog = Program { args };

self::panic::spawn_handler(&exe)?;
match el.run_app(&mut prog) {
Ok(_) => ExitCode::SUCCESS,
Err(e) => {
error(format!("Failed to run winit event loop: {}.", e.display()));
ExitCode::FAILURE
}
}
}

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

Expand Down Expand Up @@ -176,34 +197,11 @@ fn run_vmm(args: &ProgramArgs) -> Result<(), ProgramError> {
};

// Setup VMM screen.
let mut el = EventLoop::<VmmEvent>::with_user_event();

let screen = graphics
.create_screen(&profile)
.map_err(|e| ProgramError::CreateScreen(Box::new(e)))?;

// Start VMM.
let el = el.build().map_err(ProgramError::CreateVmmEventLoop)?;

std::thread::scope(|scope| {
let vmm = Vmm::new(
VmmArgs {
profile: &profile,
kernel,
debugger,
el: el.create_proxy(),
},
scope,
)
.map_err(ProgramError::StartVmm)?;

// Run the screen.
screen
.run()
.map_err(|e| ProgramError::RunScreen(Box::new(e)))?;

Ok(())
})
todo!()
}

fn run_launcher(
Expand Down Expand Up @@ -318,6 +316,49 @@ 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 Expand Up @@ -349,9 +390,6 @@ enum ProgramMode {
/// Represents an error when our program fails.
#[derive(Debug, Error)]
enum ProgramError {
#[error("couldn't spawn panic handler process")]
SpawnPanicHandler(#[source] std::io::Error),

#[cfg(unix)]
#[error("couldn't increase file descriptor limit")]
FdLimit(#[source] self::rlim::RlimitError),
Expand All @@ -371,9 +409,6 @@ enum ProgramError {
#[error("couldn't save default profile")]
SaveDefaultProfile(#[source] self::profile::SaveError),

#[error("couldn't get application executable path")]
GetCurrentExePath(#[source] std::io::Error),

#[error("failed to start debug server on {1}")]
StartDebugServer(
#[source] debug::StartDebugServerError,
Expand All @@ -394,16 +429,4 @@ enum ProgramError {

#[error("couldn't create VMM screen")]
CreateScreen(#[source] Box<dyn std::error::Error>),

#[error("couldn't create VMM event loop")]
CreateVmmEventLoop(#[source] EventLoopError),

#[error("couldn't start VMM")]
StartVmm(#[source] VmmError),

#[error("couldn't run VMM screen")]
RunScreen(#[source] Box<dyn std::error::Error>),

#[error("couldn't read panic info")]
ReadPanicInfo(#[source] ciborium::de::Error<std::io::Error>),
}
Loading

0 comments on commit 2a6aa24

Please sign in to comment.