WIP input events

Compile and passes tests. But the mouse event are currently not working
This commit is contained in:
Olivier Goffart 2020-08-06 12:33:07 +02:00
parent 829990f9b1
commit 55ec533c40
11 changed files with 96 additions and 53 deletions

View file

@ -142,13 +142,17 @@ struct Repeater
}
}
void visit(ItemVisitorRefMut visitor) const
intptr_t visit(ItemVisitorRefMut visitor) const
{
for (const auto &x : data) {
for (auto i = 0; i < data.size(); ++i) {
const auto &x = data.at(i);
VRef<ComponentVTable> ref { &C::component_type, x.get() };
ref.vtable->visit_children_item(ref, -1, visitor);
if (ref.vtable->visit_children_item(ref, -1, visitor) == -1) {
return i;
}
}
return -1;
}
};
Flickable::Flickable()

View file

@ -81,6 +81,7 @@ pub mod re_exports {
pub use sixtyfps_corelib::graphics::{
PathArcTo, PathData, PathElement, PathEvent, PathLineTo, Point, Rect, Size,
};
pub use sixtyfps_corelib::input::{InputEventResult, MouseEvent};
pub use sixtyfps_corelib::item_tree::{
visit_item_tree, ItemTreeNode, ItemVisitorRefMut, ItemVisitorVTable,
};

View file

@ -41,11 +41,14 @@ where
}
/// Call the visitor for each component
pub fn visit(&self, mut visitor: sixtyfps_corelib::item_tree::ItemVisitorRefMut) {
for c in self.components.borrow().iter() {
c.as_ref().visit_children_item(-1, visitor.borrow_mut());
pub fn visit(&self, mut visitor: sixtyfps_corelib::item_tree::ItemVisitorRefMut) -> isize {
for (i, c) in self.components.borrow().iter().enumerate() {
if c.as_ref().visit_children_item(-1, visitor.borrow_mut()) != -1 {
return i as isize;
}
}
-1
}
/// Return the amount of item currently in the component
pub fn len(&self) -> usize {

View file

@ -353,7 +353,7 @@ fn handle_repeater(
if repeated.model.is_constant() {
children_repeater_cases.push(format!(
"\n case {i}: self->{id}.visit(visitor); break;",
"\n case {i}: return self->{id}.visit(visitor);",
id = repeater_id,
i = repeater_count
));
@ -703,7 +703,7 @@ fn generate_component(
Access::Private,
Declaration::Function(Function {
name: "visit_children".into(),
signature: "(sixtyfps::ComponentRef, intptr_t, sixtyfps::ItemVisitorRefMut) -> void"
signature: "(sixtyfps::ComponentRef, intptr_t, sixtyfps::ItemVisitorRefMut) -> intptr_t"
.into(),
is_static: true,
..Default::default()
@ -742,14 +742,15 @@ fn generate_component(
declarations.push(Declaration::Function(Function {
name: format!("{}::visit_children", component_id),
signature: "(sixtyfps::ComponentRef component, intptr_t index, sixtyfps::ItemVisitorRefMut visitor) -> void".into(),
signature: "(sixtyfps::ComponentRef component, intptr_t index, sixtyfps::ItemVisitorRefMut visitor) -> intptr_t".into(),
statements: Some(vec![
"static const sixtyfps::ItemTreeNode<uint8_t> children[] {".to_owned(),
format!(" {} }};", tree_array.join(", ")),
"static const auto dyn_visit = [] (const uint8_t *base, [[maybe_unused]] sixtyfps::ItemVisitorRefMut visitor, uintptr_t dyn_index) {".to_owned(),
"static const auto dyn_visit = [] (const uint8_t *base, [[maybe_unused]] sixtyfps::ItemVisitorRefMut visitor, uintptr_t dyn_index) -> intptr_t {".to_owned(),
format!(" [[maybe_unused]] auto self = reinterpret_cast<const {}*>(base);", component_id),
// Fixme: this is not the root component
format!(" switch(dyn_index) {{ {} }}\n }};", children_visitor_case.join("")),
format!(" switch(dyn_index) {{ {} }};", children_visitor_case.join("")),
" return -1; //should not happen\n};".to_owned(),
"return sixtyfps::sixtyfps_visit_item_tree(component, { const_cast<sixtyfps::ItemTreeNode<uint8_t>*>(children), std::size(children)}, index, visitor, dyn_visit);".to_owned(),
]),
..Default::default()

View file

@ -430,12 +430,12 @@ fn generate_component(
}
impl sixtyfps::re_exports::Component for #component_id {
fn visit_children_item(self: ::core::pin::Pin<&Self>, index: isize, visitor: sixtyfps::re_exports::ItemVisitorRefMut) {
fn visit_children_item(self: ::core::pin::Pin<&Self>, index: isize, visitor: sixtyfps::re_exports::ItemVisitorRefMut) -> isize {
use sixtyfps::re_exports::*;
let tree = &[#(#item_tree_array),*];
sixtyfps::re_exports::visit_item_tree(self, VRef::new_pin(self), tree, index, visitor, visit_dynamic);
return sixtyfps::re_exports::visit_item_tree(self, VRef::new_pin(self), tree, index, visitor, visit_dynamic);
#[allow(unused)]
fn visit_dynamic(self_pinned: ::core::pin::Pin<&#component_id>, visitor: ItemVisitorRefMut, dyn_index: usize) {
fn visit_dynamic(self_pinned: ::core::pin::Pin<&#component_id>, visitor: ItemVisitorRefMut, dyn_index: usize) -> isize {
match dyn_index {
#(#repeated_visit_branch)*
_ => panic!("invalid dyn_index {}", dyn_index),
@ -443,6 +443,10 @@ fn generate_component(
}
}
fn input_event(self: ::core::pin::Pin<&Self>, _ : sixtyfps::re_exports::MouseEvent) -> sixtyfps::re_exports::InputEventResult {
todo!()
}
#layouts
}
@ -1230,7 +1234,7 @@ fn compile_path(path: &Path, component: &Rc<Component>) -> TokenStream {
}
}
}
/*
quote! {
fn process_input_event(self: ::core::pin::Pin<&Self>, mouse_event) {
@ -1253,3 +1257,4 @@ match repeater_offset => {
}
}
}
*/

View file

@ -37,7 +37,7 @@ impl FlickableData {
.get(),
)
}
MouseEventType::MouseReleased => {
MouseEventType::MouseExit | MouseEventType::MouseReleased => {
if let Some(pressed_time) = inner.pressed_time {
let dist = event.pos - inner.pressed_pos;
let speed = dist

View file

@ -447,10 +447,9 @@ impl<Backend: GraphicsBackend> crate::eventloop::GenericWindow for GraphicsWindo
what: MouseEventType,
component: crate::ComponentRefPin,
) {
crate::input::process_mouse_event(
component,
MouseEvent { pos: euclid::point2(pos.x as _, pos.y as _), what },
);
component
.as_ref()
.input_event(MouseEvent { pos: euclid::point2(pos.x as _, pos.y as _), what });
}
fn window_handle(&self) -> std::cell::Ref<winit::window::Window> {
std::cell::Ref::map(self.map_state.borrow(), |window| window.as_mapped().backend.window())

View file

@ -81,7 +81,7 @@ pub(crate) mod ffi {
base: &u8,
visitor: vtable::VRefMut<ItemVisitorVTable>,
dyn_index: usize,
) -> bool,
) -> isize,
) -> isize {
crate::item_tree::visit_item_tree(
Pin::new_unchecked(&*(component.as_ptr() as *const u8)),
@ -151,21 +151,25 @@ pub fn visit_item_tree<Base>(
item_tree: &[ItemTreeNode<Base>],
index: isize,
mut visitor: vtable::VRefMut<ItemVisitorVTable>,
visit_dynamic: impl Fn(Pin<&Base>, vtable::VRefMut<ItemVisitorVTable>, usize) -> bool,
visit_dynamic: impl Fn(Pin<&Base>, vtable::VRefMut<ItemVisitorVTable>, usize) -> isize,
) -> isize {
let mut visit_at_index = |idx: usize| -> isize {
let continue_ = match &item_tree[idx] {
match &item_tree[idx] {
ItemTreeNode::Item { item, .. } => {
visitor.visit_item(component, idx as isize, item.apply_pin(base))
if visitor.visit_item(component, idx as isize, item.apply_pin(base)) {
-1
} else {
idx as isize
}
}
ItemTreeNode::DynamicTree { index } => {
visit_dynamic(base, visitor.borrow_mut(), *index)
}
};
if continue_ {
idx as isize | continue_ << 16
} else {
let sub_idx = visit_dynamic(base, visitor.borrow_mut(), *index);
if sub_idx == -1 {
-1
} else {
idx as isize | sub_idx << 16
}
}
}
};
if index == -1 {

View file

@ -18,7 +18,7 @@ When adding an item or a property, it needs to be kept in sync with different pl
use super::abi::datastructures::{Item, ItemConsts};
use super::graphics::{Color, HighLevelRenderingPrimitive, PathData, Rect, Resource};
use super::input::{MouseEvent, MouseEventType};
use super::input::{InputEventResult, MouseEvent, MouseEventType};
use super::item_rendering::CachedRenderingData;
use super::layout::LayoutInfo;
#[cfg(feature = "rtti")]
@ -70,7 +70,9 @@ impl Item for Rectangle {
Default::default()
}
fn input_event(self: Pin<&Self>, _: MouseEvent) {}
fn input_event(self: Pin<&Self>, _: MouseEvent) -> InputEventResult {
InputEventResult::EventIgnored
}
}
impl ItemConsts for Rectangle {
@ -133,7 +135,9 @@ impl Item for BorderRectangle {
Default::default()
}
fn input_event(self: Pin<&Self>, _: MouseEvent) {}
fn input_event(self: Pin<&Self>, _: MouseEvent) -> InputEventResult {
InputEventResult::EventIgnored
}
}
impl ItemConsts for BorderRectangle {
@ -194,7 +198,9 @@ impl Item for Image {
Default::default()
}
fn input_event(self: Pin<&Self>, _: MouseEvent) {}
fn input_event(self: Pin<&Self>, _: MouseEvent) -> InputEventResult {
InputEventResult::EventIgnored
}
}
impl ItemConsts for Image {
@ -312,7 +318,9 @@ impl Item for Text {
})
}
fn input_event(self: Pin<&Self>, _: MouseEvent) {}
fn input_event(self: Pin<&Self>, _: MouseEvent) -> InputEventResult {
InputEventResult::EventIgnored
}
}
impl ItemConsts for Text {
@ -359,15 +367,16 @@ impl Item for TouchArea {
LayoutInfo::default()
}
fn input_event(self: Pin<&Self>, event: MouseEvent) {
fn input_event(self: Pin<&Self>, event: MouseEvent) -> InputEventResult {
Self::FIELD_OFFSETS.pressed.apply_pin(self).set(match event.what {
MouseEventType::MousePressed => true,
MouseEventType::MouseReleased => false,
MouseEventType::MouseMoved => return,
MouseEventType::MouseExit | MouseEventType::MouseReleased => false,
MouseEventType::MouseMoved => return InputEventResult::EventAccepted,
});
if matches!(event.what, MouseEventType::MouseReleased) {
Self::FIELD_OFFSETS.clicked.apply_pin(self).emit(())
}
InputEventResult::GrabMouse
}
}
@ -424,7 +433,9 @@ impl Item for Path {
LayoutInfo::default()
}
fn input_event(self: Pin<&Self>, _: MouseEvent) {}
fn input_event(self: Pin<&Self>, _: MouseEvent) -> InputEventResult {
InputEventResult::EventIgnored
}
}
impl ItemConsts for Path {
@ -471,8 +482,10 @@ impl Item for Flickable {
LayoutInfo::default()
}
fn input_event(self: Pin<&Self>, event: MouseEvent) {
fn input_event(self: Pin<&Self>, event: MouseEvent) -> InputEventResult {
self.data.handle_mouse(self, event);
// FIXME
InputEventResult::EventAccepted
}
}

View file

@ -142,7 +142,7 @@ unsafe extern "C" fn visit_children_item(
component: ComponentRefPin,
index: isize,
v: ItemVisitorRefMut,
) {
) -> isize {
let component_type =
&*(component.get_vtable() as *const ComponentVTable as *const ComponentDescription);
let item_tree = &component_type.it;
@ -189,11 +189,14 @@ unsafe extern "C" fn visit_children_item(
});
}
}
for x in vec {
x.borrow().as_ref().visit_children_item(-1, visitor.borrow_mut());
for (i, x) in vec.iter().enumerate() {
if x.borrow().as_ref().visit_children_item(-1, visitor.borrow_mut()) != -1 {
return i as isize;
}
}
-1
},
);
)
}
/// Information attached to a builtin item
@ -412,7 +415,7 @@ fn generate_component(root_component: &Rc<object_tree::Component>) -> Rc<Compone
todo!()
}
let t = ComponentVTable { visit_children_item, layout_info, compute_layout };
let t = ComponentVTable { visit_children_item, layout_info, compute_layout, input_event };
let t = ComponentDescription {
ct: t,
dynamic_type: builder.build(),
@ -914,6 +917,13 @@ impl<'a> LayoutTreeItem<'a> {
}
}
extern "C" fn input_event(
_component: ComponentRefPin,
_mouse: sixtyfps_corelib::input::MouseEvent,
) -> sixtyfps_corelib::input::InputEventResult {
todo!()
}
unsafe extern "C" fn compute_layout(component: ComponentRefPin) {
// This is fine since we can only be called with a component that with our vtable which is a ComponentDescription
let component_type =

View file

@ -7,7 +7,7 @@ use core::pin::Pin;
use cpp::cpp;
use sixtyfps_corelib::abi::datastructures::{Item, ItemConsts, ItemVTable};
use sixtyfps_corelib::graphics::{HighLevelRenderingPrimitive, Rect, RenderingVariable, Resource};
use sixtyfps_corelib::input::{MouseEvent, MouseEventType};
use sixtyfps_corelib::input::{InputEventResult, MouseEvent, MouseEventType};
use sixtyfps_corelib::item_rendering::CachedRenderingData;
use sixtyfps_corelib::layout::LayoutInfo;
#[cfg(feature = "rtti")]
@ -130,15 +130,16 @@ impl Item for QtStyleButton {
LayoutInfo::default()
}
fn input_event(self: Pin<&Self>, event: MouseEvent) {
fn input_event(self: Pin<&Self>, event: MouseEvent) -> InputEventResult {
Self::FIELD_OFFSETS.pressed.apply_pin(self).set(match event.what {
MouseEventType::MousePressed => true,
MouseEventType::MouseReleased => false,
MouseEventType::MouseMoved => return,
MouseEventType::MouseExit | MouseEventType::MouseReleased => false,
MouseEventType::MouseMoved => return InputEventResult::EventAccepted,
});
if matches!(event.what, MouseEventType::MouseReleased) {
Self::FIELD_OFFSETS.clicked.apply_pin(self).emit(())
}
InputEventResult::GrabMouse
}
}
@ -234,7 +235,7 @@ impl Item for QtStyleCheckBox {
LayoutInfo::default()
}
fn input_event(self: Pin<&Self>, event: MouseEvent) {
fn input_event(self: Pin<&Self>, event: MouseEvent) -> InputEventResult {
if matches!(event.what, MouseEventType::MouseReleased) {
Self::FIELD_OFFSETS
.checked
@ -242,6 +243,7 @@ impl Item for QtStyleCheckBox {
.set(!Self::FIELD_OFFSETS.checked.apply_pin(self).get());
Self::FIELD_OFFSETS.toggled.apply_pin(self).emit(())
}
InputEventResult::GrabMouse
}
}
@ -379,7 +381,7 @@ impl Item for QtStyleSpinBox {
LayoutInfo::default()
}
fn input_event(self: Pin<&Self>, event: MouseEvent) {
fn input_event(self: Pin<&Self>, event: MouseEvent) -> InputEventResult {
#[cfg(have_qt)]
{
let size: qttypes::QSize = qttypes::QSize {
@ -413,7 +415,7 @@ impl Item for QtStyleSpinBox {
data.pressed = true;
true
}
MouseEventType::MouseReleased => {
MouseEventType::MouseExit | MouseEventType::MouseReleased => {
data.pressed = false;
if new_control
== cpp!(unsafe []->u32 as "int" { return QStyle::SC_SpinBoxUp;})
@ -434,6 +436,7 @@ impl Item for QtStyleSpinBox {
self.data.set(data);
}
}
InputEventResult::GrabMouse
}
}