Skip to content

Commit

Permalink
Initializes WindowAdapter implementation (#1178)
Browse files Browse the repository at this point in the history
  • Loading branch information
ultimaweapon authored Dec 12, 2024
1 parent a000119 commit 0996ba7
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 18 deletions.
11 changes: 1 addition & 10 deletions gui/main_window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@
#include <fcntl.h>
#endif

MainWindow::MainWindow() :
m_main(nullptr)
MainWindow::MainWindow()
{
// File menu.
auto fileMenu = menuBar()->addMenu("&File");
Expand All @@ -36,19 +35,11 @@ MainWindow::MainWindow() :

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

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

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

// Central widget.
m_main = new QStackedWidget();

setCentralWidget(m_main);
}

MainWindow::~MainWindow()
Expand Down
4 changes: 0 additions & 4 deletions gui/main_window.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,10 @@
#include <QList>
#include <QMainWindow>

class QStackedWidget;

class MainWindow final : public QMainWindow {
public:
MainWindow();
~MainWindow() override;
private slots:
void aboutObliteration();
private:
QStackedWidget *m_main;
};
37 changes: 37 additions & 0 deletions gui/src/rt/context.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use std::cell::Cell;
use std::mem::transmute;
use std::ptr::null;
use winit::event_loop::ActiveEventLoop;

/// Execution context of the runtime.
pub struct RuntimeContext<'a> {
el: &'a ActiveEventLoop,
}

impl<'a> RuntimeContext<'a> {
pub(super) fn new(el: &'a ActiveEventLoop) -> Self {
Self { el }
}

/// # Panics
/// If called from the other thread than main thread.
pub fn with<R>(f: impl FnOnce(&Self) -> R) -> R {
let cx = CONTEXT.get();
assert!(!cx.is_null());
unsafe { f(&*cx) }
}

pub fn event_loop(&self) -> &ActiveEventLoop {
self.el
}

pub(super) fn run(&self, f: impl FnOnce()) {
assert!(CONTEXT.replace(unsafe { transmute(self) }).is_null());
f();
CONTEXT.set(null());
}
}

thread_local! {
static CONTEXT: Cell<*const RuntimeContext<'static>> = Cell::new(null());
}
10 changes: 8 additions & 2 deletions gui/src/rt/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
pub use self::context::*;

use futures::executor::LocalPool;
use futures::task::LocalSpawnExt;
use std::future::Future;
Expand All @@ -8,6 +10,8 @@ use winit::event::WindowEvent;
use winit::event_loop::{ActiveEventLoop, EventLoop};
use winit::window::WindowId;

mod context;

pub fn block_on(main: impl Future<Output = ()> + 'static) -> Result<(), RuntimeError> {
// Setup winit event loop.
let mut el = EventLoop::<Event>::with_user_event();
Expand All @@ -17,7 +21,7 @@ pub fn block_on(main: impl Future<Output = ()> + 'static) -> Result<(), RuntimeE
exe.spawner()
.spawn_local(async move {
main.await;
todo!()
RuntimeContext::with(|cx| cx.event_loop().exit());
})
.unwrap();

Expand All @@ -31,7 +35,9 @@ struct AsyncExecutor(LocalPool);

impl ApplicationHandler<Event> for AsyncExecutor {
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
self.0.run_until_stalled();
let cx = RuntimeContext::new(event_loop);

cx.run(|| self.0.run_until_stalled());
}

fn window_event(
Expand Down
26 changes: 24 additions & 2 deletions gui/src/ui/backend/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
use self::window::Window;
use crate::rt::RuntimeContext;
use i_slint_renderer_skia::SkiaRenderer;
use slint::platform::WindowAdapter;
use slint::PlatformError;
use slint::{PhysicalSize, PlatformError};
use std::rc::Rc;

mod window;

/// Back-end for Slint to run on top of winit event loop.
///
/// This back-end does not supports [`slint::run_event_loop()`].
Expand All @@ -15,6 +20,23 @@ impl SlintBackend {

impl slint::platform::Platform for SlintBackend {
fn create_window_adapter(&self) -> Result<Rc<dyn WindowAdapter>, PlatformError> {
todo!()
// Create winit window.
let attrs = winit::window::Window::default_attributes();
let win = match RuntimeContext::with(move |cx| cx.event_loop().create_window(attrs)) {
Ok(v) => Rc::new(v),
Err(e) => return Err(PlatformError::OtherError(Box::new(e))),
};

// Create WindowAdapter.
let size = win.inner_size();
let renderer = SkiaRenderer::new(
win.clone(),
win.clone(),
PhysicalSize::new(size.width, size.height),
)?;

Ok(Rc::<Window>::new_cyclic(move |weak| {
Window::new(win, slint::Window::new(weak.clone()), renderer)
}))
}
}
41 changes: 41 additions & 0 deletions gui/src/ui/backend/window.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use i_slint_renderer_skia::SkiaRenderer;
use slint::platform::{Renderer, WindowAdapter};
use slint::PhysicalSize;
use std::rc::Rc;

/// Implementation of [`WindowAdapter`].
pub struct Window {
winit: Rc<winit::window::Window>,
slint: slint::Window,
renderer: SkiaRenderer,
}

impl Window {
pub fn new(
winit: Rc<winit::window::Window>,
slint: slint::Window,
renderer: SkiaRenderer,
) -> Self {
Self {
winit,
slint,
renderer,
}
}
}

impl WindowAdapter for Window {
fn window(&self) -> &slint::Window {
&self.slint
}

fn size(&self) -> PhysicalSize {
let s = self.winit.inner_size();

PhysicalSize::new(s.width, s.height)
}

fn renderer(&self) -> &dyn Renderer {
&self.renderer
}
}

0 comments on commit 0996ba7

Please sign in to comment.