mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-01 14:21:16 +00:00
Start a new sixtyfps::Window API for Rust, C++, the interpreters and JS
The generated component now provides access to a Window type via the window() accessor function. This is part of #333
This commit is contained in:
parent
5fd63b63f1
commit
66891a299c
14 changed files with 200 additions and 50 deletions
|
@ -13,6 +13,8 @@ This class will have the following public member functions:
|
||||||
and react to user input, it's still necessary to spin the event loop, by calling {cpp:func}`sixtyfps::run_event_loop()`
|
and react to user input, it's still necessary to spin the event loop, by calling {cpp:func}`sixtyfps::run_event_loop()`
|
||||||
or using the convenience `fun` function in this class.
|
or using the convenience `fun` function in this class.
|
||||||
* A `hide` function, which de-registers the component from the windowing system.
|
* A `hide` function, which de-registers the component from the windowing system.
|
||||||
|
* A `window` function that provides access to the {cpp:class}`sixtyfps::Window`, allow for further customization
|
||||||
|
towards the windowing system.
|
||||||
* A `run` convenience function, which will show the component and starts the event loop.
|
* A `run` convenience function, which will show the component and starts the event loop.
|
||||||
* for each properties:
|
* for each properties:
|
||||||
* A getter `get_<property_name>` returning the property type.
|
* A getter `get_<property_name>` returning the property type.
|
||||||
|
|
|
@ -82,6 +82,7 @@ using cbindgen_private::KeyEvent;
|
||||||
class WindowRc
|
class WindowRc
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
explicit WindowRc(cbindgen_private::WindowRcOpaque adopted_inner) : inner(adopted_inner) { }
|
||||||
WindowRc() { cbindgen_private::sixtyfps_windowrc_init(&inner); }
|
WindowRc() { cbindgen_private::sixtyfps_windowrc_init(&inner); }
|
||||||
~WindowRc() { cbindgen_private::sixtyfps_windowrc_drop(&inner); }
|
~WindowRc() { cbindgen_private::sixtyfps_windowrc_drop(&inner); }
|
||||||
WindowRc(const WindowRc &other)
|
WindowRc(const WindowRc &other)
|
||||||
|
@ -89,7 +90,15 @@ public:
|
||||||
cbindgen_private::sixtyfps_windowrc_clone(&other.inner, &inner);
|
cbindgen_private::sixtyfps_windowrc_clone(&other.inner, &inner);
|
||||||
}
|
}
|
||||||
WindowRc(WindowRc &&) = delete;
|
WindowRc(WindowRc &&) = delete;
|
||||||
WindowRc &operator=(const WindowRc &) = delete;
|
WindowRc &operator=(WindowRc &&) = delete;
|
||||||
|
WindowRc &operator=(const WindowRc &other)
|
||||||
|
{
|
||||||
|
if (this != &other) {
|
||||||
|
cbindgen_private::sixtyfps_windowrc_drop(&inner);
|
||||||
|
cbindgen_private::sixtyfps_windowrc_clone(&other.inner, &inner);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
void show() const { sixtyfps_windowrc_show(&inner); }
|
void show() const { sixtyfps_windowrc_show(&inner); }
|
||||||
void hide() const { sixtyfps_windowrc_hide(&inner); }
|
void hide() const { sixtyfps_windowrc_hide(&inner); }
|
||||||
|
@ -257,6 +266,40 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// This class represents a window towards the windowing system, that's used to render the
|
||||||
|
/// scene of a component. It provides API to control windowing system specific aspects such
|
||||||
|
/// as the position on the screen.
|
||||||
|
class Window
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// \private
|
||||||
|
/// Internal function used by the generated code to construct a new instance of this
|
||||||
|
/// public API wrapper.
|
||||||
|
explicit Window(const private_api::WindowRc &windowrc) : inner(windowrc) { }
|
||||||
|
/// Copy-constructs a new window from \a other. Window instances are explicitly
|
||||||
|
/// shared and reference counted. Creating a copy will not create a second window
|
||||||
|
/// on the screen.
|
||||||
|
Window(const Window &other) = default;
|
||||||
|
/// Copy-constructs the window \a other to this and returns a reference to this.
|
||||||
|
/// Window instances are explicitly shared and reference counted. Creating a copy
|
||||||
|
/// will not create a second window on the screen.
|
||||||
|
Window &operator=(const Window &other) = default;
|
||||||
|
Window(Window &&other) = delete;
|
||||||
|
Window &operator=(Window &&other) = delete;
|
||||||
|
/// Destroys this window. Window instances are explicitly shared and reference counted.
|
||||||
|
/// If this window instance is the last one referencing the window towards the windowing
|
||||||
|
/// system, then it will also become hidden and destroyed.
|
||||||
|
~Window() = default;
|
||||||
|
|
||||||
|
/// Registers the window with the windowing system in order to make it visible on the screen.
|
||||||
|
void show() const { inner.show(); }
|
||||||
|
/// De-registers the window from the windowing system, therefore hiding it.
|
||||||
|
void hide() const { inner.hide(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
private_api::WindowRc inner;
|
||||||
|
};
|
||||||
|
|
||||||
/// A Timer that can call a callback at repeated interval
|
/// A Timer that can call a callback at repeated interval
|
||||||
///
|
///
|
||||||
/// Use the static single_shot function to make a single shot timer
|
/// Use the static single_shot function to make a single shot timer
|
||||||
|
|
|
@ -585,6 +585,15 @@ public:
|
||||||
{
|
{
|
||||||
cbindgen_private::sixtyfps_interpreter_component_instance_show(inner(), false);
|
cbindgen_private::sixtyfps_interpreter_component_instance_show(inner(), false);
|
||||||
}
|
}
|
||||||
|
/// Returns the Window associated with this component. The window API can be used
|
||||||
|
/// to control different aspects of the integration into the windowing system,
|
||||||
|
/// such as the position on the screen.
|
||||||
|
sixtyfps::Window window() const
|
||||||
|
{
|
||||||
|
cbindgen_private::WindowRcOpaque win;
|
||||||
|
cbindgen_private::sixtyfps_interpreter_component_instance_window(inner(), &win);
|
||||||
|
return sixtyfps::Window(sixtyfps::private_api::WindowRc(win));
|
||||||
|
}
|
||||||
/// This is a convenience function that first calls show(), followed by
|
/// This is a convenience function that first calls show(), followed by
|
||||||
/// sixtyfps::run_event_loop() and hide().
|
/// sixtyfps::run_event_loop() and hide().
|
||||||
void run() const
|
void run() const
|
||||||
|
|
|
@ -13,7 +13,8 @@ LICENSE END */
|
||||||
|
|
||||||
namespace sixtyfps::testing {
|
namespace sixtyfps::testing {
|
||||||
|
|
||||||
inline void init() {
|
inline void init()
|
||||||
|
{
|
||||||
cbindgen_private::sixtyfps_testing_init_backend();
|
cbindgen_private::sixtyfps_testing_init_backend();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +26,7 @@ template<typename Component>
|
||||||
inline void send_mouse_click(const Component *component, float x, float y)
|
inline void send_mouse_click(const Component *component, float x, float y)
|
||||||
{
|
{
|
||||||
auto crc = *component->self_weak.into_dyn().lock();
|
auto crc = *component->self_weak.into_dyn().lock();
|
||||||
cbindgen_private::sixtyfps_send_mouse_click(&crc, x, y, &component->window);
|
cbindgen_private::sixtyfps_send_mouse_click(&crc, x, y, &component->window_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Component>
|
template<typename Component>
|
||||||
|
@ -33,7 +34,7 @@ inline void send_keyboard_string_sequence(const Component *component,
|
||||||
const sixtyfps::SharedString &str,
|
const sixtyfps::SharedString &str,
|
||||||
cbindgen_private::KeyboardModifiers modifiers = {})
|
cbindgen_private::KeyboardModifiers modifiers = {})
|
||||||
{
|
{
|
||||||
cbindgen_private::send_keyboard_string_sequence(&str, modifiers, &component->window);
|
cbindgen_private::send_keyboard_string_sequence(&str, modifiers, &component->window_);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define assert_eq(A, B) \
|
#define assert_eq(A, B) \
|
||||||
|
|
|
@ -41,11 +41,15 @@ class Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
show() {
|
show() {
|
||||||
this.comp.show();
|
this.window.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
hide() {
|
hide() {
|
||||||
this.comp.hide();
|
this.window.hide()
|
||||||
|
}
|
||||||
|
|
||||||
|
get window(): Window {
|
||||||
|
return this.comp.window();
|
||||||
}
|
}
|
||||||
|
|
||||||
send_mouse_click(x: number, y: number) {
|
send_mouse_click(x: number, y: number) {
|
||||||
|
@ -57,6 +61,11 @@ class Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface Window {
|
||||||
|
show(): void;
|
||||||
|
hide(): void;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -18,6 +18,7 @@ mod persistent_context;
|
||||||
|
|
||||||
struct WrappedComponentType(Option<sixtyfps_interpreter::ComponentDefinition>);
|
struct WrappedComponentType(Option<sixtyfps_interpreter::ComponentDefinition>);
|
||||||
struct WrappedComponentRc(Option<sixtyfps_interpreter::ComponentInstance>);
|
struct WrappedComponentRc(Option<sixtyfps_interpreter::ComponentInstance>);
|
||||||
|
struct WrappedWindow(Option<sixtyfps_interpreter::Window>);
|
||||||
|
|
||||||
/// We need to do some gymnastic with closures to pass the ExecuteContext with the right lifetime
|
/// We need to do some gymnastic with closures to pass the ExecuteContext with the right lifetime
|
||||||
type GlobalContextCallback<'c> =
|
type GlobalContextCallback<'c> =
|
||||||
|
@ -344,25 +345,14 @@ declare_types! {
|
||||||
})?;
|
})?;
|
||||||
Ok(JsUndefined::new().as_value(&mut cx))
|
Ok(JsUndefined::new().as_value(&mut cx))
|
||||||
}
|
}
|
||||||
method show(mut cx) {
|
method window(mut cx) {
|
||||||
let this = cx.this();
|
let this = cx.this();
|
||||||
let component = cx.borrow(&this, |x| x.0.as_ref().map(|c| c.clone_strong()));
|
let component = cx.borrow(&this, |x| x.0.as_ref().map(|c| c.clone_strong()));
|
||||||
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(), || {
|
let window = component.window();
|
||||||
component.show();
|
let mut obj = SixtyFpsWindow::new::<_, JsValue, _>(&mut cx, std::iter::empty())?;
|
||||||
Ok(())
|
cx.borrow_mut(&mut obj, |mut obj| obj.0 = Some(window));
|
||||||
})?;
|
Ok(obj.as_value(&mut cx))
|
||||||
Ok(JsUndefined::new().as_value(&mut cx))
|
|
||||||
}
|
|
||||||
method hide(mut cx) {
|
|
||||||
let this = cx.this();
|
|
||||||
let component = cx.borrow(&this, |x| x.0.as_ref().map(|c| c.clone_strong()));
|
|
||||||
let component = component.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
|
|
||||||
run_scoped(&mut cx,this.downcast().unwrap(), || {
|
|
||||||
component.hide();
|
|
||||||
Ok(())
|
|
||||||
})?;
|
|
||||||
Ok(JsUndefined::new().as_value(&mut cx))
|
|
||||||
}
|
}
|
||||||
method get_property(mut cx) {
|
method get_property(mut cx) {
|
||||||
let prop_name = cx.argument::<JsString>(0)?.value();
|
let prop_name = cx.argument::<JsString>(0)?.value();
|
||||||
|
@ -485,6 +475,28 @@ declare_types! {
|
||||||
Ok(JsUndefined::new().as_value(&mut cx))
|
Ok(JsUndefined::new().as_value(&mut cx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SixtyFpsWindow for WrappedWindow {
|
||||||
|
init(_) {
|
||||||
|
Ok(WrappedWindow(None))
|
||||||
|
}
|
||||||
|
|
||||||
|
method show(mut cx) {
|
||||||
|
let this = cx.this();
|
||||||
|
let window = cx.borrow(&this, |x| x.0.as_ref().map(|c| c.clone()));
|
||||||
|
let window = window.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
|
||||||
|
window.show();
|
||||||
|
Ok(JsUndefined::new().as_value(&mut cx))
|
||||||
|
}
|
||||||
|
|
||||||
|
method hide(mut cx) {
|
||||||
|
let this = cx.this();
|
||||||
|
let window = cx.borrow(&this, |x| x.0.as_ref().map(|c| c.clone()));
|
||||||
|
let window = window.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
|
||||||
|
window.hide();
|
||||||
|
Ok(JsUndefined::new().as_value(&mut cx))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn singleshot_timer_property(id: u32) -> String {
|
fn singleshot_timer_property(id: u32) -> String {
|
||||||
|
|
|
@ -56,6 +56,7 @@ pub mod generated_code {
|
||||||
use crate::re_exports;
|
use crate::re_exports;
|
||||||
use crate::ComponentHandle;
|
use crate::ComponentHandle;
|
||||||
use crate::Weak;
|
use crate::Weak;
|
||||||
|
use crate::Window;
|
||||||
|
|
||||||
/// This an example of the API that is generated for a component in `.60` design markup. This may help you understand
|
/// This an example of the API that is generated for a component in `.60` design markup. This may help you understand
|
||||||
/// what functions you can call and how you can pass data in and out.
|
/// what functions you can call and how you can pass data in and out.
|
||||||
|
@ -146,6 +147,13 @@ pub mod generated_code {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the Window associated with this component. The window API can be used
|
||||||
|
/// to control different aspects of the integration into the windowing system,
|
||||||
|
/// such as the position on the screen.
|
||||||
|
fn window(&self) -> Window {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
/// This is a convenience function that first calls [`Self::show`], followed by [`crate::run_event_loop()`]
|
/// This is a convenience function that first calls [`Self::show`], followed by [`crate::run_event_loop()`]
|
||||||
/// and [`Self::hide`].
|
/// and [`Self::hide`].
|
||||||
fn run(&self) {
|
fn run(&self) {
|
||||||
|
|
|
@ -450,6 +450,11 @@ pub trait ComponentHandle {
|
||||||
/// the window from the windowing system and it will not receive any further events.
|
/// the window from the windowing system and it will not receive any further events.
|
||||||
fn hide(&self);
|
fn hide(&self);
|
||||||
|
|
||||||
|
/// Returns the Window associated with this component. The window API can be used
|
||||||
|
/// to control different aspects of the integration into the windowing system,
|
||||||
|
/// such as the position on the screen.
|
||||||
|
fn window(&self) -> Window;
|
||||||
|
|
||||||
/// This is a convenience function that first calls [`Self::show`], followed by [`crate::run_event_loop()`]
|
/// This is a convenience function that first calls [`Self::show`], followed by [`crate::run_event_loop()`]
|
||||||
/// and [`Self::hide`].
|
/// and [`Self::hide`].
|
||||||
fn run(&self);
|
fn run(&self);
|
||||||
|
@ -554,6 +559,8 @@ mod weak_handle {
|
||||||
|
|
||||||
pub use weak_handle::*;
|
pub use weak_handle::*;
|
||||||
|
|
||||||
|
pub use sixtyfps_corelib::window::api::Window;
|
||||||
|
|
||||||
/// This module contains functions useful for unit tests
|
/// This module contains functions useful for unit tests
|
||||||
pub mod testing {
|
pub mod testing {
|
||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
|
|
|
@ -90,6 +90,7 @@
|
||||||
"untracked",
|
"untracked",
|
||||||
"vtable",
|
"vtable",
|
||||||
"wasm",
|
"wasm",
|
||||||
|
"windowrc", // used in sixtyfps_windowrc_foo FFI functions
|
||||||
"xtask"
|
"xtask"
|
||||||
],
|
],
|
||||||
"ignorePaths": [
|
"ignorePaths": [
|
||||||
|
|
|
@ -901,7 +901,7 @@ fn generate_component(
|
||||||
Access::Private,
|
Access::Private,
|
||||||
Declaration::Var(Var {
|
Declaration::Var(Var {
|
||||||
ty: "sixtyfps::private_api::WindowRc".into(),
|
ty: "sixtyfps::private_api::WindowRc".into(),
|
||||||
name: "window".into(),
|
name: "window_".into(),
|
||||||
..Var::default()
|
..Var::default()
|
||||||
}),
|
}),
|
||||||
));
|
));
|
||||||
|
@ -910,7 +910,7 @@ fn generate_component(
|
||||||
Access::Public, // FIXME: many of the different component bindings need to access this
|
Access::Public, // FIXME: many of the different component bindings need to access this
|
||||||
Declaration::Var(Var {
|
Declaration::Var(Var {
|
||||||
ty: "sixtyfps::private_api::WindowRc".into(),
|
ty: "sixtyfps::private_api::WindowRc".into(),
|
||||||
name: "window".into(),
|
name: "window_".into(),
|
||||||
..Var::default()
|
..Var::default()
|
||||||
}),
|
}),
|
||||||
));
|
));
|
||||||
|
@ -932,7 +932,7 @@ fn generate_component(
|
||||||
Declaration::Function(Function {
|
Declaration::Function(Function {
|
||||||
name: "show".into(),
|
name: "show".into(),
|
||||||
signature: "() const".into(),
|
signature: "() const".into(),
|
||||||
statements: Some(vec!["window.show();".into()]),
|
statements: Some(vec!["window_.show();".into()]),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
));
|
));
|
||||||
|
@ -942,7 +942,17 @@ fn generate_component(
|
||||||
Declaration::Function(Function {
|
Declaration::Function(Function {
|
||||||
name: "hide".into(),
|
name: "hide".into(),
|
||||||
signature: "() const".into(),
|
signature: "() const".into(),
|
||||||
statements: Some(vec!["window.hide();".into()]),
|
statements: Some(vec!["window_.hide();".into()]),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
));
|
||||||
|
|
||||||
|
component_struct.members.push((
|
||||||
|
Access::Public,
|
||||||
|
Declaration::Function(Function {
|
||||||
|
name: "window".into(),
|
||||||
|
signature: "() const -> sixtyfps::Window".into(),
|
||||||
|
statements: Some(vec!["return sixtyfps::Window(window_);".into()]),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
));
|
));
|
||||||
|
@ -961,7 +971,7 @@ fn generate_component(
|
||||||
}),
|
}),
|
||||||
));
|
));
|
||||||
|
|
||||||
init.push("self->window.init_items(this, item_tree());".into());
|
init.push("self->window_.init_items(this, item_tree());".into());
|
||||||
|
|
||||||
component_struct.friends.push("sixtyfps::private_api::WindowRc".into());
|
component_struct.friends.push("sixtyfps::private_api::WindowRc".into());
|
||||||
}
|
}
|
||||||
|
@ -976,7 +986,7 @@ fn generate_component(
|
||||||
];
|
];
|
||||||
|
|
||||||
if component.parent_element.upgrade().is_none() {
|
if component.parent_element.upgrade().is_none() {
|
||||||
create_code.push("self->window.set_component(**self->self_weak.lock());".into());
|
create_code.push("self->window_.set_component(**self->self_weak.lock());".into());
|
||||||
}
|
}
|
||||||
|
|
||||||
create_code.extend(
|
create_code.extend(
|
||||||
|
@ -1088,7 +1098,7 @@ fn generate_component(
|
||||||
is_constructor_or_destructor: true,
|
is_constructor_or_destructor: true,
|
||||||
statements: Some(init),
|
statements: Some(init),
|
||||||
constructor_member_initializers: if !component.is_global() && !is_root {
|
constructor_member_initializers: if !component.is_global() && !is_root {
|
||||||
vec!["window(parent->window)".into()]
|
vec!["window_(parent->window_)".into()]
|
||||||
} else {
|
} else {
|
||||||
vec![]
|
vec![]
|
||||||
},
|
},
|
||||||
|
@ -1117,7 +1127,7 @@ fn generate_component(
|
||||||
.join(","),
|
.join(","),
|
||||||
);
|
);
|
||||||
destructor.push("};".into());
|
destructor.push("};".into());
|
||||||
destructor.push("window.free_graphics_resources(sixtyfps::Slice<sixtyfps::private_api::ItemRef>{items, std::size(items)});".into());
|
destructor.push("window_.free_graphics_resources(sixtyfps::Slice<sixtyfps::private_api::ItemRef>{items, std::size(items)});".into());
|
||||||
}
|
}
|
||||||
|
|
||||||
component_struct.members.push((
|
component_struct.members.push((
|
||||||
|
@ -1404,7 +1414,7 @@ fn compile_expression(
|
||||||
),
|
),
|
||||||
Expression::BuiltinFunctionReference(funcref, _) => match funcref {
|
Expression::BuiltinFunctionReference(funcref, _) => match funcref {
|
||||||
BuiltinFunction::GetWindowScaleFactor => {
|
BuiltinFunction::GetWindowScaleFactor => {
|
||||||
"self->window.scale_factor".into()
|
"self->window_.scale_factor".into()
|
||||||
}
|
}
|
||||||
BuiltinFunction::Debug => {
|
BuiltinFunction::Debug => {
|
||||||
"[](auto... args){ (std::cout << ... << args) << std::endl; return nullptr; }"
|
"[](auto... args){ (std::cout << ... << args) << std::endl; return nullptr; }"
|
||||||
|
@ -1423,10 +1433,10 @@ fn compile_expression(
|
||||||
BuiltinFunction::ACos => format!("[](float a){{ return std::acos(a) / {}; }}", std::f32::consts::PI / 180.),
|
BuiltinFunction::ACos => format!("[](float a){{ return std::acos(a) / {}; }}", std::f32::consts::PI / 180.),
|
||||||
BuiltinFunction::ATan => format!("[](float a){{ return std::atan(a) / {}; }}", std::f32::consts::PI / 180.),
|
BuiltinFunction::ATan => format!("[](float a){{ return std::atan(a) / {}; }}", std::f32::consts::PI / 180.),
|
||||||
BuiltinFunction::SetFocusItem => {
|
BuiltinFunction::SetFocusItem => {
|
||||||
"self->window.set_focus_item".into()
|
"self->window_.set_focus_item".into()
|
||||||
}
|
}
|
||||||
BuiltinFunction::ShowPopupWindow => {
|
BuiltinFunction::ShowPopupWindow => {
|
||||||
"self->window.show_popup".into()
|
"self->window_.show_popup".into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/* std::from_chars is unfortunately not yet implemented in gcc
|
/* std::from_chars is unfortunately not yet implemented in gcc
|
||||||
|
@ -1562,7 +1572,7 @@ fn compile_expression(
|
||||||
if let Expression::ElementReference(focus_item) = &arguments[0] {
|
if let Expression::ElementReference(focus_item) = &arguments[0] {
|
||||||
let focus_item = focus_item.upgrade().unwrap();
|
let focus_item = focus_item.upgrade().unwrap();
|
||||||
let focus_item = focus_item.borrow();
|
let focus_item = focus_item.borrow();
|
||||||
format!("self->window.set_focus_item(self->self_weak.lock()->into_dyn(), {});", focus_item.item_index.get().unwrap())
|
format!("self->window_.set_focus_item(self->self_weak.lock()->into_dyn(), {});", focus_item.item_index.get().unwrap())
|
||||||
} else {
|
} else {
|
||||||
panic!("internal error: argument to SetFocusItem must be an element")
|
panic!("internal error: argument to SetFocusItem must be an element")
|
||||||
}
|
}
|
||||||
|
@ -1580,7 +1590,7 @@ fn compile_expression(
|
||||||
let popup = popup_list.iter().find(|p| Rc::ptr_eq(&p.component, &pop_comp)).unwrap();
|
let popup = popup_list.iter().find(|p| Rc::ptr_eq(&p.component, &pop_comp)).unwrap();
|
||||||
let x = access_named_reference(&popup.x, component, "self");
|
let x = access_named_reference(&popup.x, component, "self");
|
||||||
let y = access_named_reference(&popup.y, component, "self");
|
let y = access_named_reference(&popup.y, component, "self");
|
||||||
format!("self->window.show_popup<{}>(self, {{ {}.get(), {}.get() }} );", popup_window_id, x, y)
|
format!("self->window_.show_popup<{}>(self, {{ {}.get(), {}.get() }} );", popup_window_id, x, y)
|
||||||
} else {
|
} else {
|
||||||
panic!("internal error: argument to SetFocusItem must be an element")
|
panic!("internal error: argument to SetFocusItem must be an element")
|
||||||
}
|
}
|
||||||
|
@ -1593,7 +1603,7 @@ fn compile_expression(
|
||||||
let item = item.upgrade().unwrap();
|
let item = item.upgrade().unwrap();
|
||||||
let item = item.borrow();
|
let item = item.borrow();
|
||||||
let native_item = item.base_type.as_native();
|
let native_item = item.base_type.as_native();
|
||||||
format!("{vt}->layouting_info({{{vt}, const_cast<sixtyfps::cbindgen_private::{ty}*>(&self->{id})}}, {o}, &window)",
|
format!("{vt}->layouting_info({{{vt}, const_cast<sixtyfps::cbindgen_private::{ty}*>(&self->{id})}}, {o}, &window_)",
|
||||||
vt = native_item.cpp_vtable_getter,
|
vt = native_item.cpp_vtable_getter,
|
||||||
ty = native_item.class_name,
|
ty = native_item.class_name,
|
||||||
id = item.id,
|
id = item.id,
|
||||||
|
@ -2038,7 +2048,7 @@ fn get_layout_info(
|
||||||
format!("{}.get()", access_named_reference(layout_info_prop, component, "self"))
|
format!("{}.get()", access_named_reference(layout_info_prop, component, "self"))
|
||||||
} else {
|
} else {
|
||||||
format!(
|
format!(
|
||||||
"{vt}->layouting_info({{{vt}, const_cast<sixtyfps::cbindgen_private::{ty}*>(&self->{id})}}, {o}, &self->window)",
|
"{vt}->layouting_info({{{vt}, const_cast<sixtyfps::cbindgen_private::{ty}*>(&self->{id})}}, {o}, &self->window_)",
|
||||||
vt = elem.borrow().base_type.as_native().cpp_vtable_getter,
|
vt = elem.borrow().base_type.as_native().cpp_vtable_getter,
|
||||||
ty = elem.borrow().base_type.as_native().class_name,
|
ty = elem.borrow().base_type.as_native().class_name,
|
||||||
id = elem.borrow().id,
|
id = elem.borrow().id,
|
||||||
|
|
|
@ -849,11 +849,15 @@ fn generate_component(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show(&self) {
|
fn show(&self) {
|
||||||
vtable::VRc::as_pin_ref(&self.0).window.window_handle().show();
|
self.window().show();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hide(&self) {
|
fn hide(&self) {
|
||||||
vtable::VRc::as_pin_ref(&self.0).window.window_handle().hide();
|
self.window().hide()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn window(&self) -> sixtyfps::Window {
|
||||||
|
vtable::VRc::as_pin_ref(&self.0).window.clone().into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
|
|
|
@ -339,6 +339,44 @@ impl WindowHandleAccess for WindowRc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Internal module to define the public Window API, for re-export in the regular Rust crate
|
||||||
|
/// and the interpreter crate.
|
||||||
|
pub mod api {
|
||||||
|
/// This type represents a window towards the windowing system, that's used to render the
|
||||||
|
/// scene of a component. It provides API to control windowing system specific aspects such
|
||||||
|
/// as the position on the screen.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Window(super::WindowRc);
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
impl From<super::WindowRc> for Window {
|
||||||
|
fn from(window: super::WindowRc) -> Self {
|
||||||
|
Self(window)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Window {
|
||||||
|
/// Registers the window with the windowing system in order to make it visible on the screen.
|
||||||
|
pub fn show(&self) {
|
||||||
|
use super::WindowHandleAccess;
|
||||||
|
self.0.window_handle().show();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// De-registers the window from the windowing system, therefore hiding it.
|
||||||
|
pub fn hide(&self) {
|
||||||
|
use super::WindowHandleAccess;
|
||||||
|
self.0.window_handle().hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
impl super::WindowHandleAccess for Window {
|
||||||
|
fn window_handle(&self) -> &std::rc::Rc<super::Window> {
|
||||||
|
self.0.window_handle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// This module contains the functions needed to interface with the event loop and window traits
|
/// This module contains the functions needed to interface with the event loop and window traits
|
||||||
/// from outside the Rust language.
|
/// from outside the Rust language.
|
||||||
#[cfg(feature = "ffi")]
|
#[cfg(feature = "ffi")]
|
||||||
|
|
|
@ -11,6 +11,7 @@ LICENSE END */
|
||||||
use core::convert::TryInto;
|
use core::convert::TryInto;
|
||||||
use sixtyfps_compilerlib::langtype::Type as LangType;
|
use sixtyfps_compilerlib::langtype::Type as LangType;
|
||||||
use sixtyfps_corelib::graphics::Image;
|
use sixtyfps_corelib::graphics::Image;
|
||||||
|
use sixtyfps_corelib::window::WindowHandleAccess;
|
||||||
use sixtyfps_corelib::{Brush, PathData, SharedString, SharedVector};
|
use sixtyfps_corelib::{Brush, PathData, SharedString, SharedVector};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
|
@ -20,6 +21,8 @@ use std::rc::Rc;
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use sixtyfps_compilerlib::diagnostics::{Diagnostic, DiagnosticLevel};
|
pub use sixtyfps_compilerlib::diagnostics::{Diagnostic, DiagnosticLevel};
|
||||||
|
|
||||||
|
pub use sixtyfps_corelib::window::api::Window;
|
||||||
|
|
||||||
/// This enum represents the different public variants of the [`Value`] enum, without
|
/// This enum represents the different public variants of the [`Value`] enum, without
|
||||||
/// the contained values.
|
/// the contained values.
|
||||||
// NOTE: The docs for ValueType are duplicated in sixtyfps_interpreter.h, for extraction by
|
// NOTE: The docs for ValueType are duplicated in sixtyfps_interpreter.h, for extraction by
|
||||||
|
@ -578,13 +581,14 @@ impl ComponentDefinition {
|
||||||
/// Instantiate the component using an existing window.
|
/// Instantiate the component using an existing window.
|
||||||
/// This method is internal because the Window is not a public type
|
/// This method is internal because the Window is not a public type
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn create_with_existing_window(
|
pub fn create_with_existing_window(&self, window: Window) -> ComponentInstance {
|
||||||
&self,
|
|
||||||
window: Rc<sixtyfps_corelib::window::Window>,
|
|
||||||
) -> ComponentInstance {
|
|
||||||
generativity::make_guard!(guard);
|
generativity::make_guard!(guard);
|
||||||
ComponentInstance {
|
ComponentInstance {
|
||||||
inner: self.inner.unerase(guard).clone().create_with_existing_window(window),
|
inner: self
|
||||||
|
.inner
|
||||||
|
.unerase(guard)
|
||||||
|
.clone()
|
||||||
|
.create_with_existing_window(window.window_handle().clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -781,6 +785,7 @@ impl ComponentInstance {
|
||||||
let comp = self.inner.unerase(guard);
|
let comp = self.inner.unerase(guard);
|
||||||
comp.window().hide();
|
comp.window().hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is a convenience function that first calls [`Self::show`], followed by [`crate::run_event_loop()`]
|
/// This is a convenience function that first calls [`Self::show`], followed by [`crate::run_event_loop()`]
|
||||||
/// and [`Self::hide`].
|
/// and [`Self::hide`].
|
||||||
pub fn run(&self) {
|
pub fn run(&self) {
|
||||||
|
@ -807,13 +812,14 @@ impl ComponentInstance {
|
||||||
WeakComponentInstance { inner: vtable::VRc::downgrade(&self.inner) }
|
WeakComponentInstance { inner: vtable::VRc::downgrade(&self.inner) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the window.
|
/// Returns the Window associated with this component. The window API can be used
|
||||||
/// This method is internal because the Window is not a public type
|
/// to control different aspects of the integration into the windowing system,
|
||||||
#[doc(hidden)]
|
/// such as the position on the screen.
|
||||||
pub fn window(&self) -> Rc<sixtyfps_corelib::window::Window> {
|
pub fn window(&self) -> Window {
|
||||||
generativity::make_guard!(guard);
|
generativity::make_guard!(guard);
|
||||||
let comp = self.inner.unerase(guard);
|
let comp = self.inner.unerase(guard);
|
||||||
comp.window()
|
let window_rc: sixtyfps_corelib::window::WindowRc = comp.window().into();
|
||||||
|
window_rc.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ assert(instance.get_test_zero());
|
||||||
assert(instance.get_test());
|
assert(instance.get_test());
|
||||||
|
|
||||||
ratio = 2.;
|
ratio = 2.;
|
||||||
instance.window.set_scale_factor(ratio);
|
instance.window_.set_scale_factor(ratio);
|
||||||
assert_eq(instance.get_l1(), 12.);
|
assert_eq(instance.get_l1(), 12.);
|
||||||
assert_eq(instance.get_l2(), 12. * ratio);
|
assert_eq(instance.get_l2(), 12. * ratio);
|
||||||
assert_eq(instance.get_l3(), 100. + 12. * ratio);
|
assert_eq(instance.get_l3(), 100. + 12. * ratio);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue