mirror of
https://github.com/slint-ui/slint.git
synced 2025-09-05 10:00:35 +00:00
Get rid of abi::datastructures::WindowProperties
Instead, pass a reference to the root item when mapping the window, at which point we can downcast to the new Window item. If we have one, then we'll read its width/height (for initial values) and install bindings to keep them up-to-date.
This commit is contained in:
parent
3d5d112deb
commit
aafb96cb93
14 changed files with 150 additions and 116 deletions
|
@ -24,6 +24,7 @@ extern const internal::ItemVTable TouchAreaVTable;
|
||||||
extern const internal::ItemVTable ImageVTable;
|
extern const internal::ItemVTable ImageVTable;
|
||||||
extern const internal::ItemVTable PathVTable;
|
extern const internal::ItemVTable PathVTable;
|
||||||
extern const internal::ItemVTable FlickableVTable;
|
extern const internal::ItemVTable FlickableVTable;
|
||||||
|
extern const internal::ItemVTable WindowVTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bring opaque structure in scope
|
// Bring opaque structure in scope
|
||||||
|
@ -35,7 +36,6 @@ using internal::TraversalOrder;
|
||||||
using internal::EasingCurve;
|
using internal::EasingCurve;
|
||||||
using internal::TextHorizontalAlignment;
|
using internal::TextHorizontalAlignment;
|
||||||
using internal::TextVerticalAlignment;
|
using internal::TextVerticalAlignment;
|
||||||
using internal::WindowProperties;
|
|
||||||
using internal::Slice;
|
using internal::Slice;
|
||||||
|
|
||||||
struct ComponentWindow
|
struct ComponentWindow
|
||||||
|
@ -49,9 +49,8 @@ struct ComponentWindow
|
||||||
template<typename Component>
|
template<typename Component>
|
||||||
void run(Component *c)
|
void run(Component *c)
|
||||||
{
|
{
|
||||||
auto props = c->window_properties();
|
|
||||||
sixtyfps_component_window_run(
|
sixtyfps_component_window_run(
|
||||||
&inner, VRefMut<ComponentVTable> { &Component::component_type, c }, &props);
|
&inner, VRefMut<ComponentVTable> { &Component::component_type, c }, c->root_item());
|
||||||
}
|
}
|
||||||
|
|
||||||
float scale_factor() const { return sixtyfps_component_window_get_scale_factor(&inner); }
|
float scale_factor() const { return sixtyfps_component_window_get_scale_factor(&inner); }
|
||||||
|
@ -71,6 +70,7 @@ using internal::Path;
|
||||||
using internal::Rectangle;
|
using internal::Rectangle;
|
||||||
using internal::Text;
|
using internal::Text;
|
||||||
using internal::TouchArea;
|
using internal::TouchArea;
|
||||||
|
using internal::Window;
|
||||||
|
|
||||||
constexpr inline ItemTreeNode make_item_node(std::uintptr_t offset,
|
constexpr inline ItemTreeNode make_item_node(std::uintptr_t offset,
|
||||||
const internal::ItemVTable *vtable,
|
const internal::ItemVTable *vtable,
|
||||||
|
|
|
@ -248,7 +248,7 @@ declare_types! {
|
||||||
let component = cx.borrow(&mut this, |x| x.0.clone());
|
let component = cx.borrow(&mut this, |x| x.0.clone());
|
||||||
let component = component.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
|
let component = component.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
|
||||||
run_scoped(&mut cx,this.downcast().unwrap(), || {
|
run_scoped(&mut cx,this.downcast().unwrap(), || {
|
||||||
component.window().run(component.borrow(), &component.window_properties());
|
component.window().run(component.borrow(), component.root_item());
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
Ok(JsUndefined::new().as_value(&mut cx))
|
Ok(JsUndefined::new().as_value(&mut cx))
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Button, CheckBox, SpinBox, Slider } from "sixtyfps_widgets.60";
|
import { Button, CheckBox, SpinBox, Slider } from "sixtyfps_widgets.60";
|
||||||
|
|
||||||
App := Rectangle {
|
App := Window {
|
||||||
GridLayout {
|
GridLayout {
|
||||||
spacing: 10lx;
|
spacing: 10lx;
|
||||||
Row {
|
Row {
|
||||||
|
|
|
@ -115,7 +115,7 @@ SettingsPage := Page {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow := Rectangle {
|
MainWindow := Window {
|
||||||
|
|
||||||
width: 800lx;
|
width: 800lx;
|
||||||
height: 600lx;
|
height: 600lx;
|
||||||
|
|
|
@ -642,24 +642,16 @@ fn generate_component(
|
||||||
}),
|
}),
|
||||||
));
|
));
|
||||||
|
|
||||||
let window_props = |name| {
|
let root_elem = component.root_element.borrow();
|
||||||
let root_elem = component.root_element.borrow();
|
|
||||||
|
|
||||||
if root_elem.lookup_property(name) == Type::Length {
|
|
||||||
format!("&this->{}.{}", root_elem.id, name)
|
|
||||||
} else {
|
|
||||||
"nullptr".to_owned()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
component_struct.members.push((
|
component_struct.members.push((
|
||||||
Access::Public,
|
Access::Public,
|
||||||
Declaration::Function(Function {
|
Declaration::Function(Function {
|
||||||
name: "window_properties".into(),
|
name: "root_item".into(),
|
||||||
signature: "() -> sixtyfps::WindowProperties".into(),
|
signature: "() -> VRef<sixtyfps::internal::ItemVTable>".into(),
|
||||||
statements: Some(vec![format!(
|
statements: Some(vec![format!(
|
||||||
"return {{ {} , {} }};",
|
"return {{ &sixtyfps::{vt}, &this->{id} }};",
|
||||||
window_props("width"),
|
vt = root_elem.base_type.as_native().vtable_symbol,
|
||||||
window_props("height")
|
id = root_elem.id
|
||||||
)]),
|
)]),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -373,26 +373,14 @@ fn generate_component(
|
||||||
// FIXME: This field is public for testing.
|
// FIXME: This field is public for testing.
|
||||||
maybe_window_field_decl.push(quote!(pub window: sixtyfps::re_exports::ComponentWindow));
|
maybe_window_field_decl.push(quote!(pub window: sixtyfps::re_exports::ComponentWindow));
|
||||||
maybe_window_field_init.push(quote!(window: sixtyfps::create_window()));
|
maybe_window_field_init.push(quote!(window: sixtyfps::create_window()));
|
||||||
let window_props = |name| {
|
|
||||||
let root_elem = component.root_element.borrow();
|
|
||||||
|
|
||||||
if root_elem.lookup_property(name) == Type::Length {
|
let root_elem = component.root_element.borrow();
|
||||||
let root_item_name = quote::format_ident!("{}", root_elem.id);
|
let root_item_name = quote::format_ident!("{}", root_elem.id);
|
||||||
let root_item_ty =
|
|
||||||
quote::format_ident!("{}", root_elem.base_type.as_native().class_name);
|
|
||||||
let name = quote::format_ident!("{}", name);
|
|
||||||
quote!(Some((Self::FIELD_OFFSETS.#root_item_name + #root_item_ty::FIELD_OFFSETS.#name).apply_pin(self.as_ref())))
|
|
||||||
} else {
|
|
||||||
quote!(None)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let width_prop = window_props("width");
|
|
||||||
let height_prop = window_props("height");
|
|
||||||
property_and_signal_accessors.push(quote! {
|
property_and_signal_accessors.push(quote! {
|
||||||
pub fn run(self : core::pin::Pin<std::rc::Rc<Self>>) {
|
pub fn run(self : core::pin::Pin<std::rc::Rc<Self>>) {
|
||||||
use sixtyfps::re_exports::*;
|
use sixtyfps::re_exports::*;
|
||||||
let window_props = WindowProperties {width: #width_prop, height: #height_prop};
|
let root_item = Self::FIELD_OFFSETS.#root_item_name.apply_pin(self.as_ref());
|
||||||
self.as_ref().window.run(VRef::new_pin(self.as_ref()), &window_props);
|
self.as_ref().window.run(VRef::new_pin(self.as_ref()), VRef::new_pin(root_item));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
property_and_signal_accessors.push(quote! {
|
property_and_signal_accessors.push(quote! {
|
||||||
|
|
|
@ -534,6 +534,8 @@ impl TypeRegister {
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
native_class(&mut r, "Window", &[("width", Type::Length), ("height", Type::Length)]);
|
||||||
|
|
||||||
let mut grid_layout = BuiltinElement::new(Rc::new(NativeClass::new("GridLayout")));
|
let mut grid_layout = BuiltinElement::new(Rc::new(NativeClass::new("GridLayout")));
|
||||||
grid_layout.properties.insert("spacing".to_owned(), Type::Length);
|
grid_layout.properties.insert("spacing".to_owned(), Type::Length);
|
||||||
|
|
||||||
|
|
|
@ -73,22 +73,6 @@ pub struct ItemVTable {
|
||||||
/// the associated vtable
|
/// the associated vtable
|
||||||
pub type ItemRef<'a> = vtable::VRef<'a, ItemVTable>;
|
pub type ItemRef<'a> = vtable::VRef<'a, ItemVTable>;
|
||||||
|
|
||||||
/// Alias for Option<Pin<&'a Property<T>>> to faciliate cbindgen.
|
|
||||||
pub type PinnedOptionalProp<'a, T> = Option<core::pin::Pin<&'a crate::Property<T>>>;
|
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Default)]
|
|
||||||
/// WindowProperties is used to pass the references to properties of the instantiated
|
|
||||||
/// component that the run-time will keep up-to-date.
|
|
||||||
pub struct WindowProperties<'a> {
|
|
||||||
/// A reference to the property that is supposed to be kept up-to-date with the width
|
|
||||||
/// of the window.
|
|
||||||
pub width: PinnedOptionalProp<'a, f32>,
|
|
||||||
/// A reference to the property that is supposed to be kept up-to-date with the height
|
|
||||||
/// of the window.
|
|
||||||
pub height: PinnedOptionalProp<'a, f32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is here because for some reason (rust bug?) the ItemVTable_static is not accessible in the other modules
|
// This is here because for some reason (rust bug?) the ItemVTable_static is not accessible in the other modules
|
||||||
|
|
||||||
ItemVTable_static! {
|
ItemVTable_static! {
|
||||||
|
@ -127,3 +111,9 @@ ItemVTable_static! {
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub static FlickableVTable for crate::items::Flickable
|
pub static FlickableVTable for crate::items::Flickable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ItemVTable_static! {
|
||||||
|
/// The VTable for `Window`
|
||||||
|
#[no_mangle]
|
||||||
|
pub static WindowVTable for crate::items::Window
|
||||||
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ fn main() {
|
||||||
"EasingCurve",
|
"EasingCurve",
|
||||||
"TextHorizontalAlignment",
|
"TextHorizontalAlignment",
|
||||||
"TextVerticalAlignment",
|
"TextVerticalAlignment",
|
||||||
|
"Window",
|
||||||
]
|
]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|x| x.to_string())
|
.map(|x| x.to_string())
|
||||||
|
@ -33,7 +34,6 @@ fn main() {
|
||||||
"PathElement",
|
"PathElement",
|
||||||
"sixtyfps_new_path_elements",
|
"sixtyfps_new_path_elements",
|
||||||
"sixtyfps_new_path_events",
|
"sixtyfps_new_path_events",
|
||||||
"PinnedOptionalProp",
|
|
||||||
]
|
]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|x| x.to_string())
|
.map(|x| x.to_string())
|
||||||
|
@ -186,7 +186,7 @@ fn main() {
|
||||||
.with_include("sixtyfps_color.h")
|
.with_include("sixtyfps_color.h")
|
||||||
.with_include("sixtyfps_pathdata.h")
|
.with_include("sixtyfps_pathdata.h")
|
||||||
.with_after_include(format!(
|
.with_after_include(format!(
|
||||||
"namespace sixtyfps {{ enum class VersionCheck {{ Major = {}, Minor = {}, Patch = {} }}; }}\nnamespace sixtyfps {{ namespace internal {{ template <typename T> using PinnedOptionalProp = Property<T> *; }} }}",
|
"namespace sixtyfps {{ enum class VersionCheck {{ Major = {}, Minor = {}, Patch = {} }}; }}",
|
||||||
env!("CARGO_PKG_VERSION_MAJOR"),
|
env!("CARGO_PKG_VERSION_MAJOR"),
|
||||||
env!("CARGO_PKG_VERSION_MINOR"),
|
env!("CARGO_PKG_VERSION_MINOR"),
|
||||||
env!("CARGO_PKG_VERSION_PATCH")
|
env!("CARGO_PKG_VERSION_PATCH")
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::abi::datastructures::{ComponentVTable, WindowProperties};
|
use crate::abi::datastructures::{ComponentVTable, ItemRef};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::{
|
use std::{
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
|
@ -19,11 +19,13 @@ pub trait GenericWindow {
|
||||||
component: core::pin::Pin<crate::abi::datastructures::ComponentRef>,
|
component: core::pin::Pin<crate::abi::datastructures::ComponentRef>,
|
||||||
);
|
);
|
||||||
fn window_handle(&self) -> std::cell::Ref<'_, winit::window::Window>;
|
fn window_handle(&self) -> std::cell::Ref<'_, winit::window::Window>;
|
||||||
fn map_window(self: Rc<Self>, event_loop: &EventLoop, props: &WindowProperties);
|
fn map_window(self: Rc<Self>, event_loop: &EventLoop, root_item: Pin<ItemRef>);
|
||||||
fn unmap_window(self: Rc<Self>);
|
fn unmap_window(self: Rc<Self>);
|
||||||
fn request_redraw(&self);
|
fn request_redraw(&self);
|
||||||
fn scale_factor(&self) -> f32;
|
fn scale_factor(&self) -> f32;
|
||||||
fn set_scale_factor(&self, factor: f32);
|
fn set_scale_factor(&self, factor: f32);
|
||||||
|
fn set_width(&self, width: f32);
|
||||||
|
fn set_height(&self, height: f32);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The ComponentWindow is the (rust) facing public type that can render the items
|
/// The ComponentWindow is the (rust) facing public type that can render the items
|
||||||
|
@ -39,12 +41,12 @@ impl ComponentWindow {
|
||||||
Self(window_impl)
|
Self(window_impl)
|
||||||
}
|
}
|
||||||
/// Spins an event loop and renders the items of the provided component in this window.
|
/// Spins an event loop and renders the items of the provided component in this window.
|
||||||
pub fn run(&self, component: Pin<VRef<ComponentVTable>>, props: &WindowProperties) {
|
pub fn run(&self, component: Pin<VRef<ComponentVTable>>, root_item: Pin<ItemRef>) {
|
||||||
let event_loop = crate::eventloop::EventLoop::new();
|
let event_loop = crate::eventloop::EventLoop::new();
|
||||||
|
|
||||||
self.0.clone().map_window(&event_loop, props);
|
self.0.clone().map_window(&event_loop, root_item);
|
||||||
|
|
||||||
event_loop.run(component, &props);
|
event_loop.run(component);
|
||||||
|
|
||||||
self.0.clone().unmap_window();
|
self.0.clone().unmap_window();
|
||||||
}
|
}
|
||||||
|
@ -83,11 +85,7 @@ impl EventLoop {
|
||||||
Self { winit_loop: winit::event_loop::EventLoop::new() }
|
Self { winit_loop: winit::event_loop::EventLoop::new() }
|
||||||
}
|
}
|
||||||
#[allow(unused_mut)] // mut need changes for wasm
|
#[allow(unused_mut)] // mut need changes for wasm
|
||||||
pub fn run(
|
pub fn run(mut self, component: core::pin::Pin<crate::abi::datastructures::ComponentRef>) {
|
||||||
mut self,
|
|
||||||
component: core::pin::Pin<crate::abi::datastructures::ComponentRef>,
|
|
||||||
window_properties: &crate::abi::datastructures::WindowProperties,
|
|
||||||
) {
|
|
||||||
use winit::event::Event;
|
use winit::event::Event;
|
||||||
use winit::event_loop::{ControlFlow, EventLoopWindowTarget};
|
use winit::event_loop::{ControlFlow, EventLoopWindowTarget};
|
||||||
let layout_listener = Rc::pin(PropertyListenerScope::default());
|
let layout_listener = Rc::pin(PropertyListenerScope::default());
|
||||||
|
@ -122,19 +120,14 @@ impl EventLoop {
|
||||||
event: winit::event::WindowEvent::Resized(size),
|
event: winit::event::WindowEvent::Resized(size),
|
||||||
window_id,
|
window_id,
|
||||||
} => {
|
} => {
|
||||||
if let Some(width_property) = window_properties.width {
|
|
||||||
width_property.set(size.width as f32)
|
|
||||||
}
|
|
||||||
if let Some(height_property) = window_properties.height {
|
|
||||||
height_property.set(size.height as f32)
|
|
||||||
}
|
|
||||||
|
|
||||||
ALL_WINDOWS.with(|windows| {
|
ALL_WINDOWS.with(|windows| {
|
||||||
if let Some(Some(window)) =
|
if let Some(Some(window)) =
|
||||||
windows.borrow().get(&window_id).map(|weakref| weakref.upgrade())
|
windows.borrow().get(&window_id).map(|weakref| weakref.upgrade())
|
||||||
{
|
{
|
||||||
let platform_window = window.window_handle();
|
let platform_window = window.window_handle();
|
||||||
window.set_scale_factor(platform_window.scale_factor() as f32)
|
window.set_scale_factor(platform_window.scale_factor() as f32);
|
||||||
|
window.set_width(size.width as f32);
|
||||||
|
window.set_height(size.height as f32);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -146,17 +139,13 @@ impl EventLoop {
|
||||||
},
|
},
|
||||||
window_id,
|
window_id,
|
||||||
} => {
|
} => {
|
||||||
if let Some(width_property) = window_properties.width {
|
|
||||||
width_property.set(size.width as f32)
|
|
||||||
}
|
|
||||||
if let Some(height_property) = window_properties.height {
|
|
||||||
height_property.set(size.height as f32)
|
|
||||||
}
|
|
||||||
ALL_WINDOWS.with(|windows| {
|
ALL_WINDOWS.with(|windows| {
|
||||||
if let Some(Some(window)) =
|
if let Some(Some(window)) =
|
||||||
windows.borrow().get(&window_id).map(|weakref| weakref.upgrade())
|
windows.borrow().get(&window_id).map(|weakref| weakref.upgrade())
|
||||||
{
|
{
|
||||||
window.set_scale_factor(scale_factor as f32)
|
window.set_scale_factor(scale_factor as f32);
|
||||||
|
window.set_width(size.width as f32);
|
||||||
|
window.set_height(size.height as f32);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -280,6 +269,7 @@ pub mod ffi {
|
||||||
#![allow(unsafe_code)]
|
#![allow(unsafe_code)]
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::abi::datastructures::ItemVTable;
|
||||||
|
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
type c_void = ();
|
type c_void = ();
|
||||||
|
@ -303,11 +293,10 @@ pub mod ffi {
|
||||||
pub unsafe extern "C" fn sixtyfps_component_window_run(
|
pub unsafe extern "C" fn sixtyfps_component_window_run(
|
||||||
handle: *mut ComponentWindowOpaque,
|
handle: *mut ComponentWindowOpaque,
|
||||||
component: Pin<VRef<ComponentVTable>>,
|
component: Pin<VRef<ComponentVTable>>,
|
||||||
window_props: *mut WindowProperties,
|
root_item: Pin<VRef<ItemVTable>>,
|
||||||
) {
|
) {
|
||||||
let window = &*(handle as *const ComponentWindow);
|
let window = &*(handle as *const ComponentWindow);
|
||||||
let window_props = &*(window_props as *const WindowProperties);
|
window.run(component, root_item);
|
||||||
window.run(component, &window_props);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the window scale factor.
|
/// Returns the window scale factor.
|
||||||
|
|
|
@ -3,7 +3,7 @@ use crate::input::{MouseEvent, MouseEventType};
|
||||||
use crate::properties::{InterpolatedPropertyValue, Property};
|
use crate::properties::{InterpolatedPropertyValue, Property};
|
||||||
#[cfg(feature = "rtti")]
|
#[cfg(feature = "rtti")]
|
||||||
use crate::rtti::{BuiltinItem, FieldInfo, FieldOffset, PropertyInfo, ValueType};
|
use crate::rtti::{BuiltinItem, FieldInfo, FieldOffset, PropertyInfo, ValueType};
|
||||||
use crate::SharedArray;
|
use crate::{abi::datastructures::ItemRef, SharedArray};
|
||||||
|
|
||||||
use cgmath::Matrix4;
|
use cgmath::Matrix4;
|
||||||
use const_field_offset::FieldOffsets;
|
use const_field_offset::FieldOffsets;
|
||||||
|
@ -366,11 +366,29 @@ impl<Backend: GraphicsBackend + 'static> GraphicsWindowBackendState<Backend> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(FieldOffsets)]
|
||||||
|
#[repr(C)]
|
||||||
|
#[pin]
|
||||||
|
struct WindowProperties {
|
||||||
|
scale_factor: Property<f32>,
|
||||||
|
width: Property<f32>,
|
||||||
|
height: Property<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for WindowProperties {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
scale_factor: Property::new(1.0),
|
||||||
|
width: Property::new(800.),
|
||||||
|
height: Property::new(600.),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct GraphicsWindow<Backend: GraphicsBackend + 'static> {
|
pub struct GraphicsWindow<Backend: GraphicsBackend + 'static> {
|
||||||
window_factory: Box<WindowFactoryFn<Backend>>,
|
window_factory: Box<WindowFactoryFn<Backend>>,
|
||||||
map_state: RefCell<GraphicsWindowBackendState<Backend>>,
|
map_state: RefCell<GraphicsWindowBackendState<Backend>>,
|
||||||
/// Turn into a struct when we get more properties later.
|
properties: Pin<Box<WindowProperties>>,
|
||||||
scale_factor: Pin<Box<Property<f32>>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Backend: GraphicsBackend + 'static> GraphicsWindow<Backend> {
|
impl<Backend: GraphicsBackend + 'static> GraphicsWindow<Backend> {
|
||||||
|
@ -381,7 +399,7 @@ impl<Backend: GraphicsBackend + 'static> GraphicsWindow<Backend> {
|
||||||
Rc::new(Self {
|
Rc::new(Self {
|
||||||
window_factory: Box::new(graphics_backend_factory),
|
window_factory: Box::new(graphics_backend_factory),
|
||||||
map_state: RefCell::new(GraphicsWindowBackendState::Unmapped),
|
map_state: RefCell::new(GraphicsWindowBackendState::Unmapped),
|
||||||
scale_factor: Box::pin(Property::new(1.0)),
|
properties: Box::pin(WindowProperties::default()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -455,7 +473,7 @@ impl<Backend: GraphicsBackend> crate::eventloop::GenericWindow for GraphicsWindo
|
||||||
fn map_window(
|
fn map_window(
|
||||||
self: Rc<Self>,
|
self: Rc<Self>,
|
||||||
event_loop: &crate::eventloop::EventLoop,
|
event_loop: &crate::eventloop::EventLoop,
|
||||||
props: &crate::abi::datastructures::WindowProperties,
|
root_item: Pin<ItemRef>,
|
||||||
) {
|
) {
|
||||||
if matches!(&*self.map_state.borrow(), GraphicsWindowBackendState::Mapped(..)) {
|
if matches!(&*self.map_state.borrow(), GraphicsWindowBackendState::Mapped(..)) {
|
||||||
return;
|
return;
|
||||||
|
@ -476,31 +494,49 @@ impl<Backend: GraphicsBackend> crate::eventloop::GenericWindow for GraphicsWindo
|
||||||
// the scale factor.
|
// the scale factor.
|
||||||
// We could pass the logical requested size at window builder time, *if* we knew what the values are.
|
// We could pass the logical requested size at window builder time, *if* we knew what the values are.
|
||||||
{
|
{
|
||||||
self.scale_factor.as_ref().set(platform_window.scale_factor() as _);
|
self.properties.as_ref().scale_factor.set(platform_window.scale_factor() as _);
|
||||||
let existing_size = platform_window.inner_size();
|
let existing_size = platform_window.inner_size();
|
||||||
|
|
||||||
let mut new_size = existing_size;
|
let mut new_size = existing_size;
|
||||||
|
|
||||||
if let Some(width_property) = props.width {
|
if let Some(window_item) = ItemRef::downcast_pin(root_item) {
|
||||||
let width = width_property.get();
|
let width =
|
||||||
|
crate::items::Window::FIELD_OFFSETS.width.apply_pin(window_item).get();
|
||||||
if width > 0. {
|
if width > 0. {
|
||||||
new_size.width = width as _;
|
new_size.width = width as _;
|
||||||
}
|
}
|
||||||
}
|
let height =
|
||||||
if let Some(height_property) = props.height {
|
crate::items::Window::FIELD_OFFSETS.height.apply_pin(window_item).get();
|
||||||
let height = height_property.get();
|
|
||||||
if height > 0. {
|
if height > 0. {
|
||||||
new_size.height = height as _;
|
new_size.height = height as _;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let window = self.clone();
|
||||||
|
window_item.as_ref().width.set_binding(move || {
|
||||||
|
WindowProperties::FIELD_OFFSETS
|
||||||
|
.width
|
||||||
|
.apply_pin(window.properties.as_ref())
|
||||||
|
.get()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let window = self.clone();
|
||||||
|
window_item.as_ref().height.set_binding(move || {
|
||||||
|
WindowProperties::FIELD_OFFSETS
|
||||||
|
.height
|
||||||
|
.apply_pin(window.properties.as_ref())
|
||||||
|
.get()
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Either request a new size or update width/height to the size given by the window manager.
|
|
||||||
if new_size != existing_size {
|
if new_size != existing_size {
|
||||||
platform_window.set_inner_size(new_size)
|
platform_window.set_inner_size(new_size)
|
||||||
} else {
|
|
||||||
props.width.map(|p| p.set(existing_size.width as _));
|
|
||||||
props.height.map(|p| p.set(existing_size.height as _));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.properties.as_ref().width.set(new_size.width as _);
|
||||||
|
self.properties.as_ref().height.set(new_size.height as _);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.map_state.replace(GraphicsWindowBackendState::Mapped(MappedWindow {
|
self.map_state.replace(GraphicsWindowBackendState::Mapped(MappedWindow {
|
||||||
|
@ -529,11 +565,19 @@ impl<Backend: GraphicsBackend> crate::eventloop::GenericWindow for GraphicsWindo
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scale_factor(&self) -> f32 {
|
fn scale_factor(&self) -> f32 {
|
||||||
self.scale_factor.as_ref().get()
|
WindowProperties::FIELD_OFFSETS.scale_factor.apply_pin(self.properties.as_ref()).get()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_scale_factor(&self, factor: f32) {
|
fn set_scale_factor(&self, factor: f32) {
|
||||||
self.scale_factor.as_ref().set(factor);
|
self.properties.as_ref().scale_factor.set(factor);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_width(&self, width: f32) {
|
||||||
|
self.properties.as_ref().width.set(width);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_height(&self, height: f32) {
|
||||||
|
self.properties.as_ref().height.set(height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -566,3 +566,44 @@ pub struct PropertyAnimation {
|
||||||
#[rtti_field]
|
#[rtti_field]
|
||||||
pub easing: crate::animations::EasingCurve,
|
pub easing: crate::animations::EasingCurve,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The implementation of the `Window` element
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(FieldOffsets, Default, BuiltinItem)]
|
||||||
|
#[pin]
|
||||||
|
pub struct Window {
|
||||||
|
pub width: Property<f32>,
|
||||||
|
pub height: Property<f32>,
|
||||||
|
pub cached_rendering_data: CachedRenderingData,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Item for Window {
|
||||||
|
fn geometry(self: Pin<&Self>) -> Rect {
|
||||||
|
euclid::rect(
|
||||||
|
0.,
|
||||||
|
0.,
|
||||||
|
Self::FIELD_OFFSETS.width.apply_pin(self).get(),
|
||||||
|
Self::FIELD_OFFSETS.height.apply_pin(self).get(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
fn rendering_primitive(self: Pin<&Self>) -> HighLevelRenderingPrimitive {
|
||||||
|
HighLevelRenderingPrimitive::NoContents
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rendering_variables(self: Pin<&Self>) -> SharedArray<RenderingVariable> {
|
||||||
|
SharedArray::from(&[])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn layouting_info(self: Pin<&Self>) -> LayoutInfo {
|
||||||
|
LayoutInfo::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn input_event(self: Pin<&Self>, _event: MouseEvent) -> InputEventResult {
|
||||||
|
InputEventResult::EventIgnored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ItemConsts for Window {
|
||||||
|
const cached_rendering_data_offset: const_field_offset::FieldOffset<Self, CachedRenderingData> =
|
||||||
|
Self::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
|
||||||
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ use object_tree::{Element, ElementRc};
|
||||||
use sixtyfps_compilerlib::layout::{GridLayout, Layout, LayoutItem, PathLayout};
|
use sixtyfps_compilerlib::layout::{GridLayout, Layout, LayoutItem, PathLayout};
|
||||||
use sixtyfps_compilerlib::typeregister::Type;
|
use sixtyfps_compilerlib::typeregister::Type;
|
||||||
use sixtyfps_compilerlib::*;
|
use sixtyfps_compilerlib::*;
|
||||||
use sixtyfps_corelib::abi::datastructures::{ComponentVTable, ItemVTable, WindowProperties};
|
use sixtyfps_corelib::abi::datastructures::{ComponentVTable, ItemRef, ItemVTable};
|
||||||
use sixtyfps_corelib::graphics::Resource;
|
use sixtyfps_corelib::graphics::Resource;
|
||||||
use sixtyfps_corelib::item_tree::{
|
use sixtyfps_corelib::item_tree::{
|
||||||
ItemTreeNode, ItemVisitorRefMut, TraversalOrder, VisitChildrenResult,
|
ItemTreeNode, ItemVisitorRefMut, TraversalOrder, VisitChildrenResult,
|
||||||
|
@ -43,7 +43,7 @@ impl<'id> ComponentBox<'id> {
|
||||||
return self.component_type.clone();
|
return self.component_type.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn window_properties<'a>(&'a self) -> WindowProperties<'a> {
|
pub fn root_item(&self) -> Pin<ItemRef> {
|
||||||
let component = self.borrow();
|
let component = self.borrow();
|
||||||
let component_type = unsafe {
|
let component_type = unsafe {
|
||||||
&*(component.get_vtable() as *const ComponentVTable as *const ComponentDescription)
|
&*(component.get_vtable() as *const ComponentVTable as *const ComponentDescription)
|
||||||
|
@ -51,20 +51,7 @@ impl<'id> ComponentBox<'id> {
|
||||||
|
|
||||||
let info = &component_type.items[component_type.original.root_element.borrow().id.as_str()];
|
let info = &component_type.items[component_type.original.root_element.borrow().id.as_str()];
|
||||||
|
|
||||||
let get_prop = |name| {
|
unsafe { info.item_from_component(component.as_ptr()) }
|
||||||
if info.elem.borrow().lookup_property(name) != Type::Length {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
info.rtti.properties.get(name).map(|p| unsafe {
|
|
||||||
Pin::new_unchecked(
|
|
||||||
&*(component.as_ptr().add(info.offset).add(p.offset())
|
|
||||||
as *const Property<f32>),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
WindowProperties { width: get_prop("width"), height: get_prop("height") }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn borrow_instance<'a>(&'a self) -> InstanceRef<'a, 'id> {
|
pub fn borrow_instance<'a>(&'a self) -> InstanceRef<'a, 'id> {
|
||||||
|
@ -338,6 +325,7 @@ fn generate_component<'id>(
|
||||||
rtti_for::<TouchArea>(),
|
rtti_for::<TouchArea>(),
|
||||||
rtti_for::<Path>(),
|
rtti_for::<Path>(),
|
||||||
rtti_for::<Flickable>(),
|
rtti_for::<Flickable>(),
|
||||||
|
rtti_for::<Window>(),
|
||||||
]
|
]
|
||||||
.iter()
|
.iter()
|
||||||
.cloned(),
|
.cloned(),
|
||||||
|
|
|
@ -36,6 +36,6 @@ fn main() -> std::io::Result<()> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let component = c.create();
|
let component = c.create();
|
||||||
component.window().run(component.borrow(), &component.window_properties());
|
component.window().run(component.borrow(), component.root_item());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue