diff --git a/crates/gosub_net/src/http/fetcher.rs b/crates/gosub_net/src/http/fetcher.rs index 305a72356..d86064725 100644 --- a/crates/gosub_net/src/http/fetcher.rs +++ b/crates/gosub_net/src/http/fetcher.rs @@ -35,6 +35,10 @@ impl Fetcher { } } + pub fn base(&self) -> &Url { + &self.base_url + } + pub async fn get_url(&self, url: &Url) -> Result { let scheme = url.scheme(); diff --git a/crates/gosub_render_backend/src/lib.rs b/crates/gosub_render_backend/src/lib.rs index 87b435a3f..b137a354e 100644 --- a/crates/gosub_render_backend/src/lib.rs +++ b/crates/gosub_render_backend/src/lib.rs @@ -5,6 +5,8 @@ use crate::layout::TextLayout; use crate::svg::SvgRenderer; pub use geo::*; use gosub_shared::async_executor::WasmNotSendSync; +use gosub_shared::traits::css3::CssSystem; +use gosub_shared::traits::render_tree::RenderTree; use gosub_shared::types::Result; use raw_window_handle::{HasDisplayHandle, HasWindowHandle}; use smallvec::SmallVec; @@ -17,10 +19,14 @@ pub trait WindowHandle: HasDisplayHandle + HasWindowHandle + Send + Sync + Clone impl WindowHandle for T where T: HasDisplayHandle + HasWindowHandle + Send + Sync + Clone {} -pub trait WindowedEventLoop: WasmNotSendSync + Clone + 'static { +pub trait WindowedEventLoop, C: CssSystem>: + WasmNotSendSync + Clone + 'static +{ fn redraw(&mut self); fn add_img_cache(&mut self, url: String, buf: ImageBuffer, size: Option); + + fn reload_from(&mut self, rt: RT); } pub trait RenderBackend: Sized + Debug + 'static { diff --git a/crates/gosub_renderer/src/draw.rs b/crates/gosub_renderer/src/draw.rs index 7afe2a0d1..b95473c1d 100644 --- a/crates/gosub_renderer/src/draw.rs +++ b/crates/gosub_renderer/src/draw.rs @@ -1,7 +1,7 @@ use crate::debug::scale::px_scale; use crate::draw::img::request_img; use crate::draw::img_cache::ImageCache; -use crate::render_tree::{load_html_rendertree, TreeDrawer}; +use crate::render_tree::{load_html_rendertree, load_html_rendertree_fetcher, TreeDrawer}; use anyhow::anyhow; use gosub_net::http::fetcher::Fetcher; use gosub_render_backend::geo::{Size, SizeU32, FP}; @@ -18,9 +18,11 @@ use gosub_shared::node::NodeId; use gosub_shared::traits::css3::{CssProperty, CssPropertyMap, CssSystem}; use gosub_shared::traits::document::Document; use gosub_shared::traits::html5::Html5Parser; +use gosub_shared::traits::render_tree; use gosub_shared::types::Result; -use log::warn; +use log::{error, info, warn}; use std::future::Future; +use std::marker::PhantomData; use std::sync::mpsc::Sender; use std::sync::{Arc, Mutex}; use url::Url; @@ -28,8 +30,14 @@ use url::Url; mod img; pub mod img_cache; -pub trait SceneDrawer, D: Document, C: CssSystem>: - WasmNotSend + 'static +pub trait SceneDrawer< + B: RenderBackend, + L: Layouter, + LT: LayoutTree, + D: Document, + C: CssSystem, + RT: render_tree::RenderTree, +>: WasmNotSend + 'static { type ImgCache: ImgCache; @@ -38,7 +46,7 @@ pub trait SceneDrawer, D: Docum backend: &mut B, data: &mut B::WindowData<'_>, size: SizeU32, - el: &impl WindowedEventLoop, + el: &impl WindowedEventLoop, ) -> bool; fn mouse_move(&mut self, backend: &mut B, x: FP, y: FP) -> bool; @@ -63,6 +71,10 @@ pub trait SceneDrawer, D: Docum fn make_dirty(&mut self); fn delete_scene(&mut self); + + fn reload>(&mut self, el: impl WindowedEventLoop); + + fn reload_from(&mut self, tree: RT); } const DEBUG_CONTENT_COLOR: (u8, u8, u8) = (0, 192, 255); //rgb(0, 192, 255) @@ -72,8 +84,8 @@ const DEBUG_BORDER_COLOR: (u8, u8, u8) = (255, 72, 72); //rgb(255, 72, 72) type Point = gosub_shared::types::Point; -impl, C: CssSystem> SceneDrawer, D, C> - for TreeDrawer +impl, C: CssSystem> + SceneDrawer, D, C, RenderTree> for TreeDrawer where <::Text as Text>::Font: From<<::TextLayout as TextLayout>::Font>, { @@ -84,7 +96,7 @@ where backend: &mut B, data: &mut B::WindowData<'_>, size: SizeU32, - el: &impl WindowedEventLoop, + el: &impl WindowedEventLoop, C>, ) -> bool { if !self.dirty && self.size == Some(size) { return false; @@ -113,6 +125,7 @@ where drawer: self, svg: Arc::new(Mutex::new(B::SVGRenderer::new())), el, + _marker: PhantomData, }; drawer.render(size); @@ -265,17 +278,63 @@ where self.tree_scene = None; self.debugger_scene = None; } + + fn reload>(&mut self, mut el: impl WindowedEventLoop, C>) { + let fetcher = self.fetcher.clone(); + + gosub_shared::async_executor::spawn(async move { + info!("Reloading tab"); + + let rt = match load_html_rendertree_fetcher::(fetcher.base().clone(), &fetcher).await { + Ok(rt) => rt, + Err(e) => { + error!("Failed to reload tab: {e}"); + return; + } + }; + + el.reload_from(rt); + }) + } + + fn reload_from(&mut self, tree: RenderTree) { + self.tree = tree; + self.size = None; + self.position = PositionTree::default(); + self.last_hover = None; + self.debugger_scene = None; + self.dirty = false; + self.tree_scene = None; + self.selected_element = None; + self.scene_transform = None; + } } -struct Drawer<'s, 't, B: RenderBackend, L: Layouter, D: Document, C: CssSystem, EL: WindowedEventLoop> { +struct Drawer< + 's, + 't, + B: RenderBackend, + L: Layouter, + D: Document, + C: CssSystem, + EL: WindowedEventLoop, + RT: render_tree::RenderTree, +> { scene: &'s mut B::Scene, drawer: &'t mut TreeDrawer, svg: Arc>, el: &'t EL, + _marker: PhantomData, } -impl, C: CssSystem, EL: WindowedEventLoop> - Drawer<'_, '_, B, L, D, C, EL> +impl< + B: RenderBackend, + L: Layouter, + D: Document, + C: CssSystem, + EL: WindowedEventLoop, + RT: render_tree::RenderTree, + > Drawer<'_, '_, B, L, D, C, EL, RT> where <::Text as Text>::Font: From<<::TextLayout as TextLayout>::Font>, { @@ -316,7 +375,7 @@ where pos.x += p.x as FP; pos.y += p.y as FP; - let (border_radius, new_size) = render_bg::( + let (border_radius, new_size) = render_bg::( node, self.scene, pos, @@ -336,7 +395,7 @@ where let size = node.layout.size_or().map(|x| x.u32()); - let img = request_img::( + let img = request_img::( self.drawer.fetcher.clone(), self.svg.clone(), url, @@ -570,14 +629,14 @@ pub fn print_tree( } */ -fn render_bg( +fn render_bg>( node: &RenderTreeNode, scene: &mut B::Scene, pos: &Point, svg: Arc>, fetcher: Arc, img_cache: &mut ImageCache, - el: &impl WindowedEventLoop, + el: &impl WindowedEventLoop, ) -> ((FP, FP, FP, FP), Option) { let bg_color = node .properties @@ -660,7 +719,7 @@ fn render_bg( if let Some(url) = background_image { let size = node.layout.size_or().map(|x| x.u32()); - let img = match request_img::(fetcher.clone(), svg.clone(), url, size, img_cache, el) { + let img = match request_img::(fetcher.clone(), svg.clone(), url, size, img_cache, el) { Ok(img) => img, Err(e) => { eprintln!("Error loading image: {:?}", e); diff --git a/crates/gosub_renderer/src/draw/img.rs b/crates/gosub_renderer/src/draw/img.rs index 46a73a348..db74f059a 100644 --- a/crates/gosub_renderer/src/draw/img.rs +++ b/crates/gosub_renderer/src/draw/img.rs @@ -10,15 +10,17 @@ use gosub_render_backend::svg::SvgRenderer; use gosub_render_backend::{ Image as _, ImageBuffer, ImageCacheEntry, ImgCache, RenderBackend, SizeU32, WindowedEventLoop, }; +use gosub_shared::traits::css3::CssSystem; +use gosub_shared::traits::render_tree::RenderTree; use gosub_shared::types::Result; -pub fn request_img( +pub fn request_img, C: CssSystem>( fetcher: Arc, svg_renderer: Arc>, url: &str, size: Option, img_cache: &mut ImageCache, - el: &impl WindowedEventLoop, + el: &impl WindowedEventLoop, ) -> Result> { let img = img_cache.get(url); diff --git a/crates/gosub_renderer/src/render_tree.rs b/crates/gosub_renderer/src/render_tree.rs index b37e211dc..3134f1fcf 100644 --- a/crates/gosub_renderer/src/render_tree.rs +++ b/crates/gosub_renderer/src/render_tree.rs @@ -70,6 +70,16 @@ pub(crate) async fn load_html_rendertree, C: CssS url: Url, ) -> gosub_shared::types::Result<(RenderTree, Fetcher)> { let fetcher = Fetcher::new(url.clone()); + + let rt = load_html_rendertree_fetcher::(url, &fetcher).await?; + + Ok((rt, fetcher)) +} + +pub(crate) async fn load_html_rendertree_fetcher, C: CssSystem>( + url: Url, + fetcher: &Fetcher, +) -> gosub_shared::types::Result> { let html = if url.scheme() == "http" || url.scheme() == "https" { // Fetch the html from the url let response = fetcher.get(url.as_ref()).await?; @@ -101,5 +111,5 @@ pub(crate) async fn load_html_rendertree, C: CssS drop(doc); - Ok((generate_render_tree(DocumentHandle::clone(&doc_handle))?, fetcher)) + generate_render_tree(DocumentHandle::clone(&doc_handle)) } diff --git a/crates/gosub_shared/src/traits/render_tree.rs b/crates/gosub_shared/src/traits/render_tree.rs index e440b0123..1fb6b97fe 100644 --- a/crates/gosub_shared/src/traits/render_tree.rs +++ b/crates/gosub_shared/src/traits/render_tree.rs @@ -1,6 +1,6 @@ use crate::traits::css3::CssSystem; -pub trait RenderTree { +pub trait RenderTree: Send + 'static { type NodeId: Copy; type Node: RenderTreeNode; diff --git a/crates/gosub_useragent/src/application.rs b/crates/gosub_useragent/src/application.rs index d80d92e2c..830221592 100644 --- a/crates/gosub_useragent/src/application.rs +++ b/crates/gosub_useragent/src/application.rs @@ -16,6 +16,7 @@ use gosub_renderer::draw::SceneDrawer; use gosub_shared::traits::css3::CssSystem; use gosub_shared::traits::document::Document; use gosub_shared::traits::html5::Html5Parser; +use gosub_shared::traits::render_tree::RenderTree; use gosub_shared::types::Result; use crate::tabs::Tab; @@ -39,38 +40,41 @@ impl WindowOptions { } } +#[allow(clippy::type_complexity)] pub struct Application< 'a, - D: SceneDrawer, + D: SceneDrawer, B: RenderBackend, L: Layouter, LT: LayoutTree, Doc: Document, C: CssSystem, P: Html5Parser, + RT: RenderTree, > { open_windows: Vec<(Vec, WindowOptions)>, // Vec of Windows, each with a Vec of URLs, representing tabs - windows: HashMap>, + windows: HashMap>, backend: B, layouter: L, #[allow(clippy::type_complexity)] - proxy: Option>>, + proxy: Option>>, #[allow(clippy::type_complexity)] - event_loop: Option>>, + event_loop: Option>>, debug: bool, _marker: std::marker::PhantomData<&'a P>, } impl< 'a, - D: SceneDrawer, + D: SceneDrawer, B: RenderBackend, L: Layouter, LT: LayoutTree, Doc: Document, C: CssSystem, P: Html5Parser, - > ApplicationHandler> for Application<'a, D, B, L, LT, Doc, C, P> + RT: RenderTree, + > ApplicationHandler> for Application<'a, D, B, L, LT, Doc, C, P, RT> { fn resumed(&mut self, _event_loop: &ActiveEventLoop) { info!("Resumed"); @@ -81,7 +85,7 @@ impl< } } - fn user_event(&mut self, event_loop: &ActiveEventLoop, event: CustomEventInternal) { + fn user_event(&mut self, event_loop: &ActiveEventLoop, event: CustomEventInternal) { match event { CustomEventInternal::OpenWindow(url, id) => { info!("Opening window with URL: {url}"); @@ -243,6 +247,15 @@ impl< tab.data.delete_scene(); + window.request_redraw(); + } + } + } + CustomEventInternal::ReloadFrom(rt, id) => { + if let Some(window) = self.windows.get_mut(&id) { + if let Some(tab) = window.tabs.get_current_tab() { + tab.reload_from(rt); + window.request_redraw(); } } @@ -252,7 +265,7 @@ impl< fn window_event(&mut self, event_loop: &ActiveEventLoop, window_id: WindowId, event: WindowEvent) { if let Some(window) = self.windows.get_mut(&window_id) { - if let Err(e) = window.event(event_loop, &mut self.backend, event) { + if let Err(e) = window.event::

(event_loop, &mut self.backend, event) { eprintln!("Error handling window event: {e:?}"); }; } @@ -267,14 +280,15 @@ impl< impl< 'a, - D: SceneDrawer, + D: SceneDrawer, B: RenderBackend, L: Layouter, LT: LayoutTree, Doc: Document, C: CssSystem, P: Html5Parser, - > Application<'a, D, B, L, LT, Doc, C, P> + RT: RenderTree, + > Application<'a, D, B, L, LT, Doc, C, P, RT> { pub fn new(backend: B, layouter: L, debug: bool) -> Self { Self { @@ -297,7 +311,7 @@ impl< self.open_windows.append(&mut windows); } - pub fn add_window(&mut self, window: Window<'a, D, B, L, LT, Doc, C>) { + pub fn add_window(&mut self, window: Window<'a, D, B, L, LT, Doc, C, RT>) { self.windows.insert(window.window.id(), window); } @@ -336,7 +350,7 @@ impl< } #[allow(clippy::type_complexity)] - pub fn proxy(&mut self) -> Result>> { + pub fn proxy(&mut self) -> Result>> { if self.proxy.is_none() { self.initialize()?; } @@ -362,16 +376,17 @@ pub enum CustomEvent { Unselect, } pub enum CustomEventInternal< - D: SceneDrawer, + D: SceneDrawer, B: RenderBackend, L: Layouter, LT: LayoutTree, Doc: Document, C: CssSystem, + RT: RenderTree, > { OpenWindow(Url, WindowOptions), OpenTab(Url, WindowId), - AddTab(Tab, WindowId), + AddTab(Tab, WindowId), CloseWindow(WindowId), OpenInitial, Select(u64), @@ -379,16 +394,18 @@ pub enum CustomEventInternal< Unselect, Redraw(WindowId), AddImg(String, ImageBuffer, Option, WindowId), + ReloadFrom(RT, WindowId), } impl< - D: SceneDrawer, + D: SceneDrawer, B: RenderBackend, L: Layouter, LT: LayoutTree, Doc: Document, C: CssSystem, - > Debug for CustomEventInternal + RT: RenderTree, + > Debug for CustomEventInternal { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { @@ -402,6 +419,7 @@ impl< Self::Unselect => f.write_str("Unselect"), Self::Redraw(_) => f.write_str("Redraw"), Self::AddImg(..) => f.write_str("AddImg"), + Self::ReloadFrom(..) => f.write_str("ReloadFrom"), } } } diff --git a/crates/gosub_useragent/src/event_loop.rs b/crates/gosub_useragent/src/event_loop.rs index aee4f6481..580f3b3ca 100644 --- a/crates/gosub_useragent/src/event_loop.rs +++ b/crates/gosub_useragent/src/event_loop.rs @@ -7,21 +7,29 @@ use gosub_render_backend::{Point, RenderBackend, SizeU32, FP}; use gosub_renderer::draw::SceneDrawer; use gosub_shared::traits::css3::CssSystem; use gosub_shared::traits::document::Document; +use gosub_shared::traits::html5::Html5Parser; +use gosub_shared::traits::render_tree::RenderTree; use gosub_shared::types::Result; use crate::window::{Window, WindowState}; impl< 'a, - D: SceneDrawer, + D: SceneDrawer, B: RenderBackend, L: Layouter, LT: LayoutTree, Doc: Document, C: CssSystem, - > Window<'a, D, B, L, LT, Doc, C> + RT: RenderTree, + > Window<'a, D, B, L, LT, Doc, C, RT> { - pub fn event(&mut self, el: &ActiveEventLoop, backend: &mut B, event: WindowEvent) -> Result<()> { + pub fn event>( + &mut self, + el: &ActiveEventLoop, + backend: &mut B, + event: WindowEvent, + ) -> Result<()> { let WindowState::Active { surface: active_window_data, } = &mut self.state @@ -107,6 +115,9 @@ impl< tab.data.clear_buffers(); self.window.request_redraw(); } + KeyCode::F5 => { + tab.reload::

(self.el.clone()); + } _ => {} } } diff --git a/crates/gosub_useragent/src/tabs.rs b/crates/gosub_useragent/src/tabs.rs index f95e80e4e..2423d3a8a 100644 --- a/crates/gosub_useragent/src/tabs.rs +++ b/crates/gosub_useragent/src/tabs.rs @@ -1,9 +1,10 @@ use gosub_render_backend::layout::{LayoutTree, Layouter}; -use gosub_render_backend::{NodeDesc, RenderBackend}; +use gosub_render_backend::{NodeDesc, RenderBackend, WindowedEventLoop}; use gosub_renderer::draw::SceneDrawer; use gosub_shared::traits::css3::CssSystem; use gosub_shared::traits::document::Document; use gosub_shared::traits::html5::Html5Parser; +use gosub_shared::traits::render_tree::RenderTree; use gosub_shared::types::Result; use log::info; use slotmap::{DefaultKey, SlotMap}; @@ -11,26 +12,29 @@ use std::sync::mpsc::Sender; use url::Url; pub struct Tabs< - D: SceneDrawer, + D: SceneDrawer, B: RenderBackend, L: Layouter, LT: LayoutTree, Doc: Document, C: CssSystem, + RT: RenderTree, > { - pub tabs: SlotMap>, + #[allow(clippy::type_complexity)] + pub tabs: SlotMap>, pub active: TabID, _marker: std::marker::PhantomData<(B, L, LT)>, } impl< - D: SceneDrawer, + D: SceneDrawer, L: Layouter, LT: LayoutTree, B: RenderBackend, Doc: Document, C: CssSystem, - > Default for Tabs + RT: RenderTree, + > Default for Tabs { fn default() -> Self { Self { @@ -42,15 +46,16 @@ impl< } impl< - D: SceneDrawer, + D: SceneDrawer, L: Layouter, LT: LayoutTree, B: RenderBackend, Doc: Document, C: CssSystem, - > Tabs + RT: RenderTree, + > Tabs { - pub fn new(initial: Tab) -> Self { + pub fn new(initial: Tab) -> Self { let mut tabs = SlotMap::new(); let active = TabID(tabs.insert(initial)); @@ -61,7 +66,7 @@ impl< } } - pub fn add_tab(&mut self, tab: Tab) -> TabID { + pub fn add_tab(&mut self, tab: Tab) -> TabID { TabID(self.tabs.insert(tab)) } @@ -73,7 +78,7 @@ impl< self.active = id; } - pub fn get_current_tab(&mut self) -> Option<&mut Tab> { + pub fn get_current_tab(&mut self) -> Option<&mut Tab> { self.tabs.get_mut(self.active.0) } @@ -108,28 +113,30 @@ impl< #[derive(Debug)] pub struct Tab< - D: SceneDrawer, + D: SceneDrawer, B: RenderBackend, L: Layouter, LT: LayoutTree, Doc: Document, C: CssSystem, + RT: RenderTree, > { pub title: String, pub url: Url, pub data: D, #[allow(clippy::type_complexity)] - _marker: std::marker::PhantomData, + _marker: std::marker::PhantomData, } impl< - D: SceneDrawer, + D: SceneDrawer, B: RenderBackend, L: Layouter, LT: LayoutTree, Doc: Document, C: CssSystem, - > Tab + RT: RenderTree, + > Tab { pub fn new(title: String, url: Url, data: D) -> Self { Self { @@ -152,6 +159,14 @@ impl< _marker: std::marker::PhantomData, }) } + + pub fn reload>(&mut self, el: impl WindowedEventLoop) { + self.data.reload::

(el); + } + + pub fn reload_from(&mut self, rt: RT) { + self.data.reload_from(rt) + } } #[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] diff --git a/crates/gosub_useragent/src/window.rs b/crates/gosub_useragent/src/window.rs index 1c6f5daf4..846b48f80 100644 --- a/crates/gosub_useragent/src/window.rs +++ b/crates/gosub_useragent/src/window.rs @@ -18,6 +18,7 @@ use gosub_renderer::draw::SceneDrawer; use gosub_shared::traits::css3::CssSystem; use gosub_shared::traits::document::Document; use gosub_shared::traits::html5::Html5Parser; +use gosub_shared::traits::render_tree::RenderTree; use gosub_shared::types::Result; use crate::application::{CustomEventInternal, WindowOptions}; @@ -52,35 +53,37 @@ static ICON: LazyCell = LazyCell::new(|| { pub struct Window< 'a, - D: SceneDrawer, + D: SceneDrawer, B: RenderBackend, L: Layouter, LT: LayoutTree, Doc: Document, C: CssSystem, + RT: RenderTree, > { pub(crate) state: WindowState<'a, B>, pub(crate) window: Arc, pub(crate) renderer_data: B::WindowData<'a>, - pub(crate) tabs: Tabs, - pub(crate) el: WindowEventLoop, + pub(crate) tabs: Tabs, + pub(crate) el: WindowEventLoop, } impl< 'a, - D: SceneDrawer, + D: SceneDrawer, B: RenderBackend, L: Layouter, LT: LayoutTree, Doc: Document, C: CssSystem, - > Window<'a, D, B, L, LT, Doc, C> + RT: RenderTree, + > Window<'a, D, B, L, LT, Doc, C, RT> { pub fn new>( event_loop: &ActiveEventLoop, backend: &mut B, opts: WindowOptions, - el: EventLoopProxy>, + el: EventLoopProxy>, ) -> Result { let window = create_window(event_loop)?; @@ -137,7 +140,7 @@ impl< Ok(()) } - pub fn add_tab(&mut self, tab: Tab) { + pub fn add_tab(&mut self, tab: Tab) { let id = self.tabs.add_tab(tab); if self.tabs.active == TabID::default() { @@ -218,25 +221,27 @@ fn create_window(event_loop: &ActiveEventLoop) -> Result> { } pub(crate) struct WindowEventLoop< - D: SceneDrawer, + D: SceneDrawer, B: RenderBackend, L: Layouter, LT: LayoutTree, Doc: Document, C: CssSystem, + RT: RenderTree, > { - proxy: EventLoopProxy>, + proxy: EventLoopProxy>, id: WindowId, } impl< - D: SceneDrawer, + D: SceneDrawer, B: RenderBackend, L: Layouter, LT: LayoutTree, Doc: Document, C: CssSystem, - > Clone for WindowEventLoop + RT: RenderTree, + > Clone for WindowEventLoop { fn clone(&self) -> Self { Self { @@ -247,13 +252,14 @@ impl< } impl< - D: SceneDrawer, + D: SceneDrawer, B: RenderBackend, L: Layouter, LT: LayoutTree, Doc: Document, C: CssSystem, - > WindowedEventLoop for WindowEventLoop + RT: RenderTree, + > WindowedEventLoop for WindowEventLoop { fn redraw(&mut self) { if let Err(e) = self.proxy.send_event(CustomEventInternal::Redraw(self.id)) { @@ -269,4 +275,10 @@ impl< error!("Failed to send event {e}"); } } + + fn reload_from(&mut self, rt: RT) { + if let Err(e) = self.proxy.send_event(CustomEventInternal::ReloadFrom(rt, self.id)) { + error!("Failed to send event {e}"); + } + } } diff --git a/src/bin/renderer.rs b/src/bin/renderer.rs index 76e798e09..3ba0d5292 100644 --- a/src/bin/renderer.rs +++ b/src/bin/renderer.rs @@ -50,7 +50,7 @@ fn main() -> Result<()> { // let mut rt = load_html_rendertree(&url)?; // - let mut application: Application = + let mut application: Application = Application::new(VelloBackend::new(), TaffyLayouter, debug); application.initial_tab(Url::parse(&url)?, WindowOptions::default());