Skip to content

Commit

Permalink
Merge pull request #1 from linebender/new_infra
Browse files Browse the repository at this point in the history
Work in progress xilem prototype
  • Loading branch information
raphlinus authored Nov 23, 2022
2 parents 7fce02f + 36cd3c5 commit ef1d907
Show file tree
Hide file tree
Showing 20 changed files with 3,831 additions and 340 deletions.
3,050 changes: 3,050 additions & 0 deletions Cargo.lock

Large diffs are not rendered by default.

32 changes: 24 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,16 +1,32 @@
[package]
name = "xilem"
version = "0.1.0"
license = "Apache-2.0"
authors = ["Raph Levien <raph@google.com>"]
edition = "2021"

# This is just a bin for now but will be a lib + examples soon

[features]
default = ["x11"]

gtk = ["glazier/gtk"]
x11 = ["glazier/x11"]
wayland = ["glazier/wayland"]

[dependencies]
"druid-shell" = "0.7"
bitflags = "1.3.2"
glazier = { git = "https://github.com/linebender/glazier", default-features = false }
piet-gpu-hal = { git = "https://github.com/linebender/piet-gpu" }
piet-gpu = { git = "https://github.com/linebender/piet-gpu" }
piet-scene = { git = "https://github.com/linebender/piet-gpu", features = ["kurbo"] }
raw-window-handle = "0.5"
png = "0.16.2"
rand = "0.7.3"
roxmltree = "0.13"
swash = "0.1.4"
bytemuck = { version = "1.7.2", features = ["derive"] }
parley = { git = "https://github.com/dfrg/parley" }
tokio = { version = "1.21", features = ["full"] }
futures-task = "0.3"
tokio = { version = "1", features = ["full"] }
bitflags = "1.3.2"

[dev-dependencies]
sha2 = "0.10"
hex = "0.4.3"
[patch."https://github.com/dfrg/fount"]
fount = { git = "https://github.com/jneem/fount" }
38 changes: 22 additions & 16 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ use std::collections::HashSet;
use std::sync::{Arc, Mutex};
use std::time::Duration;

use druid_shell::kurbo::Size;
use druid_shell::piet::{Color, Piet, RenderContext};
use druid_shell::{IdleHandle, IdleToken, WindowHandle};
use glazier::kurbo::Size;
use glazier::{IdleHandle, IdleToken, WindowHandle};
use parley::FontContext;
use tokio::runtime::Runtime;

use crate::event::{AsyncWake, EventResult};
use crate::id::IdPath;
use crate::widget::{CxState, EventCx, LayoutCx, PaintCx, Pod, UpdateCx, WidgetState};
use crate::widget::{CxState, EventCx, LayoutCx, PaintCx, Pod, Rendered, UpdateCx, WidgetState};
use crate::{
event::Event,
id::Id,
Expand All @@ -42,6 +42,7 @@ pub struct App<T, V: View<T>> {
root_pod: Option<Pod>,
size: Size,
cx: Cx,
font_cx: FontContext,
pub(crate) rt: Runtime,
}

Expand Down Expand Up @@ -92,8 +93,6 @@ enum UiState {
#[derive(Clone, Default)]
pub struct WakeQueue(Arc<Mutex<Vec<IdPath>>>);

const BG_COLOR: Color = Color::rgb8(0x27, 0x28, 0x22);

impl<T: Send + 'static, V: View<T> + 'static> App<T, V>
where
V::Element: Widget + 'static,
Expand Down Expand Up @@ -153,6 +152,7 @@ where
root_state: Default::default(),
size: Default::default(),
cx,
font_cx: FontContext::new(),
rt,
}
}
Expand All @@ -170,15 +170,14 @@ where
self.size = size;
}

pub fn paint(&mut self, piet: &mut Piet) {
let rect = self.size.to_rect();
piet.fill(rect, &BG_COLOR);

pub fn paint(&mut self) -> Rendered {
loop {
self.send_events();
// TODO: be more lazy re-rendering
self.render();
let root_pod = self.root_pod.as_mut().unwrap();
let mut cx_state = CxState::new(&self.window_handle, &mut self.events);
let mut cx_state =
CxState::new(&self.window_handle, &mut self.font_cx, &mut self.events);
let mut update_cx = UpdateCx::new(&mut cx_state, &mut self.root_state);
root_pod.update(&mut update_cx);
let mut layout_cx = LayoutCx::new(&mut cx_state, &mut self.root_state);
Expand All @@ -198,15 +197,15 @@ where
// Rerun app logic, primarily for virtualized scrolling
continue;
}
let mut paint_cx = PaintCx::new(&mut cx_state, &mut self.root_state, piet);
root_pod.paint(&mut paint_cx);
break;
let mut paint_cx = PaintCx::new(&mut cx_state, &mut self.root_state);
return root_pod.paint(&mut paint_cx);
}
}

pub fn window_event(&mut self, event: RawEvent) {
self.ensure_root();
let root_pod = self.root_pod.as_mut().unwrap();
let mut cx_state = CxState::new(&self.window_handle, &mut self.events);
let mut cx_state = CxState::new(&self.window_handle, &mut self.font_cx, &mut self.events);
let mut event_cx = EventCx::new(&mut cx_state, &mut self.root_state);
root_pod.event(&mut event_cx, &event);
self.send_events();
Expand All @@ -219,6 +218,13 @@ where
}
}

// Make sure the widget tree (root pod) is available
fn ensure_root(&mut self) {
if self.root_pod.is_none() {
self.render();
}
}

/// Run the app logic and update the widget tree.
fn render(&mut self) {
if self.render_inner(false) {
Expand Down Expand Up @@ -325,7 +331,7 @@ where
self.ui_state = UiState::Delayed;
}
}
}
},
Ok(None) => break,
Err(_) => {
self.render().await;
Expand Down
79 changes: 68 additions & 11 deletions src/app_main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@

use std::any::Any;

use druid_shell::{
kurbo::Size, Application, Cursor, HotKey, IdleToken, Menu, MouseEvent, Region, SysMods,
WinHandler, WindowBuilder, WindowHandle,
use glazier::{
kurbo::Size, Application, Cursor, HotKey, IdleToken, Menu, MouseEvent, Region, Scalable,
SysMods, WinHandler, WindowBuilder, WindowHandle,
};
use parley::FontContext;
use piet_scene::{Scene, SceneBuilder, SceneFragment};

use crate::{app::App, widget::RawEvent, View, Widget};

Expand All @@ -35,6 +37,10 @@ where
{
handle: WindowHandle,
app: App<T, V>,
pgpu_state: Option<crate::render::PgpuState>,
font_context: FontContext,
scene: Scene,
counter: u64,
}

const QUIT_MENU_ID: u32 = 0x100;
Expand All @@ -58,7 +64,7 @@ impl<T: Send + 'static, V: View<T> + 'static> AppLauncher<T, V> {
QUIT_MENU_ID,
"E&xit",
Some(&HotKey::new(SysMods::Cmd, "q")),
true,
Some(true),
false,
);
let mut menubar = Menu::new();
Expand All @@ -71,6 +77,7 @@ impl<T: Send + 'static, V: View<T> + 'static> AppLauncher<T, V> {
builder.set_handler(Box::new(main_state));
builder.set_title(self.title);
builder.set_menu(menubar);
builder.set_size(Size::new(1024., 768.));
let window = builder.build().unwrap();
window.show();
druid_app.run(None);
Expand All @@ -88,8 +95,17 @@ where

fn prepare_paint(&mut self) {}

fn paint(&mut self, piet: &mut druid_shell::piet::Piet, _: &Region) {
self.app.paint(piet);
fn paint(&mut self, _: &Region) {
let rendered = self.app.paint();
self.render(rendered.0);
self.schedule_render();
}

// TODO: temporary hack
fn idle(&mut self, _: IdleToken) {
let rendered = self.app.paint();
self.render(rendered.0);
self.schedule_render();
}

fn command(&mut self, id: u32) {
Expand Down Expand Up @@ -135,11 +151,6 @@ where
Application::global().quit()
}

fn idle(&mut self, _token: IdleToken) {
// TODO: wire up invalidation through widget hierarchy
self.handle.invalidate();
}

fn as_any(&mut self) -> &mut dyn Any {
self
}
Expand All @@ -153,7 +164,53 @@ where
let state = MainState {
handle: Default::default(),
app,
font_context: FontContext::new(),
pgpu_state: None,
scene: Scene::default(),
counter: 0,
};
state
}

#[cfg(target_os = "macos")]
fn schedule_render(&self) {
self.handle
.get_idle_handle()
.unwrap()
.schedule_idle(IdleToken::new(0));
}

#[cfg(not(target_os = "macos"))]
fn schedule_render(&self) {
self.handle.invalidate();
}

fn render(&mut self, fragment: SceneFragment) {
if self.pgpu_state.is_none() {
let handle = &self.handle;
let scale = handle.get_scale().unwrap();
let insets = handle.content_insets().to_px(scale);
let mut size = handle.get_size().to_px(scale);
size.width -= insets.x_value();
size.height -= insets.y_value();
println!("render size: {:?}", size);
self.pgpu_state = Some(
crate::render::PgpuState::new(
handle,
handle,
size.width as usize,
size.height as usize,
)
.unwrap(),
);
}
if let Some(pgpu_state) = self.pgpu_state.as_mut() {
if let Some(_timestamps) = pgpu_state.pre_render() {}
let mut builder = SceneBuilder::for_scene(&mut self.scene);
builder.append(&fragment, None);
//crate::test_scenes::render(&mut self.font_context, &mut self.scene, 0, self.counter);
self.counter += 1;
pgpu_state.render(&self.scene);
}
}
}
2 changes: 1 addition & 1 deletion src/id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub type IdPath = Vec<Id>;
impl Id {
/// Allocate a new, unique `Id`.
pub fn next() -> Id {
use druid_shell::Counter;
use glazier::Counter;
static WIDGET_ID_COUNTER: Counter = Counter::new();
Id(WIDGET_ID_COUNTER.next_nonzero())
}
Expand Down
Loading

0 comments on commit ef1d907

Please sign in to comment.