Skip to content
Draft
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
6 changes: 4 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ ash = { version = "0.38", default-features = false, features = ["std"] }
sdl3 = "0.14.0"
env_logger = "0.11.8"
glam = "0.30.0"
image = { version = "0.25.6", default-features = false }
log = "0.4.17"
pollster = "0.4.0"
wgpu = "25.0.0"
winit = "0.30.0"
image = { version = "0.25.6", default-features = false }

# TODO: Disable all default features once supported (https://github.com/rust-windowing/winit/issues/3174)
winit = { git = "https://github.com/rust-windowing/winit.git", rev = "969237f422e3d1d18821f4ee99e6be7bb6acd913", default-features = false, features = ["x11"] }
19 changes: 9 additions & 10 deletions crates/bootstrap/src/with_winit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::{
pub fn run<T: ExampleBody>(yak: Yakui, state: ExampleState, title: String, body: T) {
// Normal winit setup for an EventLoop and Window.
let event_loop = EventLoop::new().unwrap();
let window_attribute = Window::default_attributes().with_title(title);
let window_attribute = WindowAttributes::default().with_title(title);

// Set up some default state that we'll modify later.
let mut app = App {
Expand All @@ -43,25 +43,24 @@ struct App<T: ExampleBody> {
attributes: WindowAttributes,
start: Instant,

window: Option<Window>,
window: Option<Box<dyn Window>>,
graphics: Option<Graphics>,
yak_window: Option<YakuiWinit>,

body: T,
}

impl<T: ExampleBody> ApplicationHandler for App<T> {
// This is a common indicator that you can create a window.
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
let window = event_loop.create_window(self.attributes.clone()).unwrap();
window.set_ime_allowed(true);

let size = window.inner_size();
let size = window.surface_size();
let size = UVec2::new(size.width, size.height);
let sample_count = get_sample_count();

let mut graphics = pollster::block_on(Graphics::new(&window, size, sample_count));
let mut yak_window = yakui_winit::YakuiWinit::new(&window);
let mut yak_window = yakui_winit::YakuiWinit::new(&*window);

// By default, yakui_winit will measure the system's scale factor and pass
// it to yakui.
Expand Down Expand Up @@ -100,7 +99,7 @@ impl<T: ExampleBody> ApplicationHandler for App<T> {

fn window_event(
&mut self,
event_loop: &ActiveEventLoop,
event_loop: &dyn ActiveEventLoop,
_window_id: WindowId,
event: WindowEvent,
) {
Expand Down Expand Up @@ -153,16 +152,16 @@ impl<T: ExampleBody> ApplicationHandler for App<T> {
self.window.as_ref().unwrap().request_redraw();
}

WindowEvent::MouseInput { state, button, .. } => {
WindowEvent::PointerButton { state, button, .. } => {
// This print is a handy way to show which mouse events are
// handled by yakui, and which ones will make it to the
// underlying application.
if button == winit::event::MouseButton::Left {
if button.mouse_button() == winit::event::MouseButton::Left {
println!("Left mouse button {state:?}");
}
}

WindowEvent::Resized(size) => {
WindowEvent::SurfaceResized(size) => {
let inset = get_inset_override();
if let Some(inset) = inset {
let size = Vec2::new(size.width as f32, size.height as f32);
Expand Down
2 changes: 0 additions & 2 deletions crates/demo/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,11 @@ yakui-app = { path = "../yakui-app" }

env_logger.workspace = true
log.workspace = true
pollster.workspace = true
wgpu = { workspace = true, features = ["webgl"] }
winit.workspace = true

[target.'cfg(target_arch = "wasm32")'.dependencies]
console_log = "1.0.0"
console_error_panic_hook = "0.1.7"
wasm-bindgen = "0.2.84"
wasm-bindgen-futures = "0.4.34"
web-sys = "0.3.61"
188 changes: 128 additions & 60 deletions crates/demo/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,87 +1,155 @@
use winit::{
event::{Event, StartCause, WindowEvent},
event_loop::{ControlFlow, EventLoop},
window::Window,
};
use winit::application::ApplicationHandler;
use winit::event_loop::ActiveEventLoop;
use winit::window::WindowAttributes;
use winit::window::WindowId;
use winit::{event::WindowEvent, event_loop::EventLoop};
use yakui::{button, row, widgets::List, CrossAxisAlignment, Yakui};
use yakui_app::Graphics;

fn app() {
row(|| {
button("Not stretched");
let mut col = List::column();
col.cross_axis_alignment = CrossAxisAlignment::Stretch;
col.show(|| {
button("Button 1");
button("Button 2");
button("Button 3");
use yakui_app::YakuiApp;

struct DemoApp;

impl App for DemoApp {
fn render(&mut self) {
row(|| {
button("Not stretched");
let mut col = List::column();
col.cross_axis_alignment = CrossAxisAlignment::Stretch;
col.show(|| {
button("Button 1");
button("Button 2");
button("Button 3");
});
});
});
}
}

trait App {
fn render(&mut self);
}

async fn run(event_loop: EventLoop<()>, window: Window) {
let mut yak = Yakui::new();
let mut graphics = Graphics::new(&window, 4).await;
struct AppHandler<T: App> {
app: T,
yak: Yakui,

event_loop.set_control_flow(ControlFlow::Poll);
#[allow(deprecated)] // winit!! :shake fist:
event_loop
.run(move |event, event_loop| match event {
Event::AboutToWait => {
window.request_redraw();
}
context: Option<YakuiApp>,

// https://github.com/rust-windowing/winit/issues/3406
#[cfg(target_os = "ios")]
redraw_requested: bool,
}

Event::NewEvents(cause) => {
graphics.is_init = cause == StartCause::Init;
impl<T: App> AppHandler<T> {
fn new(app: T) -> Self {
Self {
app: app,
yak: Yakui::new(),

context: None,

#[cfg(target_os = "ios")]
redraw_requested: false,
}
}
}

impl<T: App> ApplicationHandler for AppHandler<T> {
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
if self.context.is_some() {
return;
}

let window_attributes = {
#[cfg(not(target_arch = "wasm32"))]
{
WindowAttributes::default()
}

Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
yak.start();
app();
yak.finish();
#[cfg(target_arch = "wasm32")]
{
use platform::web::WindowAttributesWeb;

graphics.paint(&mut yak, wgpu::Color::BLACK);
WindowAttributes::default().with_platform_attributes(Box::new(
WindowAttributesWeb::default().with_append(true), // Automatically append `Canvas` to DOM.
));
}
};

Event::WindowEvent { event, .. } => {
graphics.handle_window_event(&mut yak, &event, event_loop);
let window = event_loop.create_window(window_attributes).unwrap();

self.context = Some(YakuiApp::new(window, 4));
}

fn destroy_surfaces(&mut self, _event_loop: &dyn ActiveEventLoop) {
self.context = None;
}

fn window_event(
&mut self,
event_loop: &dyn ActiveEventLoop,
_window_id: WindowId,
event: WindowEvent,
) {
let context = match self.context.as_mut() {
Some(context) => context,
None => return,
};

if context.handle_window_event(&mut self.yak, &event, event_loop) {
return;
}

match event {
WindowEvent::RedrawRequested => {
// Render
if let Some(graphics) = context.graphics_mut() {
self.yak.start();
self.app.render();
self.yak.finish();

graphics.paint(&mut self.yak, wgpu::Color::BLACK);
}

// Request Redraw
context.window.request_redraw();

#[cfg(target_os = "ios")]
{
self.redraw_requested = true;
}
}
_ => (),
})
.unwrap();
}
}

fn about_to_wait(&mut self, _event_loop: &dyn ActiveEventLoop) {
#[cfg(target_os = "ios")]
if self.redraw_requested {
if let Some(context) = self.context.as_ref() {
context.window.request_redraw();
}
self.redraw_requested = false;
}
}
}

fn main() {
let event_loop = EventLoop::new().unwrap();
#[allow(deprecated)]
let window = event_loop
.create_window(winit::window::Window::default_attributes())
.unwrap();

#[cfg(not(target_arch = "wasm32"))]
{
env_logger::init();
pollster::block_on(run(event_loop, window));
EventLoop::new()
.unwrap()
.run_app(AppHandler::new(DemoApp))
.unwrap();
}

#[cfg(target_arch = "wasm32")]
{
use winit::platform::web::WindowExtWebSys;

std::panic::set_hook(Box::new(console_error_panic_hook::hook));
console_log::init().expect("could not initialize logger");
// On wasm, append the canvas to the document body
web_sys::window()
.and_then(|win| win.document())
.and_then(|doc| doc.body())
.and_then(|body| {
body.append_child(&web_sys::Element::from(window.canvas().unwrap()))
.ok()
})
.expect("couldn't append canvas to document body");
wasm_bindgen_futures::spawn_local(run(event_loop, window));

EventLoop::new()
.unwrap()
.spawn_app(AppHandler::new(DemoApp))
.unwrap();
}
}
3 changes: 2 additions & 1 deletion crates/yakui-app/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ yakui-core = { path = "../yakui-core", version = "0.3.0" }
yakui-winit = { path = "../yakui-winit", version = "0.3.0" }
yakui-wgpu = { path = "../yakui-wgpu", version = "0.3.0" }

futures = "0.3.31"
profiling = { version = "1.0.6", optional = true }
winit = { version = "0.30.0" }
winit.workspace = true
wgpu.workspace = true
Loading