mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-02 14:51:15 +00:00
Rework and simplify the focus handling
Instead of determining the focus item through item tree traversal and pointer comparison and storing the intermediate indices in the components in the tree, remember the focus item by a pair of VWeak<ComponentVTable, Dyn> and item_index: usize. This speeds up determining the focus item as well as delivering events, which can now be done directly after retrieving an ItemRef with get_item_ref. This also fixes the duplicate line edit focus in the 7gui cells test case.
This commit is contained in:
parent
2cc1070b7b
commit
89e0b57627
20 changed files with 189 additions and 560 deletions
|
@ -98,9 +98,10 @@ public:
|
|||
cbindgen_private::sixtyfps_component_window_free_graphics_resources(&inner, &items);
|
||||
}
|
||||
|
||||
void set_focus_item(vtable::VRef<ComponentVTable> c, vtable::VRef<ItemVTable> item)
|
||||
void set_focus_item(const ComponentRc &component_rc, uintptr_t item_index)
|
||||
{
|
||||
cbindgen_private::sixtyfps_component_window_set_focus_item(&inner, c, item);
|
||||
cbindgen_private::sixtyfps_component_window_set_focus_item(&inner, &component_rc,
|
||||
item_index);
|
||||
}
|
||||
|
||||
template<typename Component, typename ItemTree>
|
||||
|
@ -167,7 +168,6 @@ inline ItemRef get_item_ref(ComponentRef component, Slice<ItemTreeNode> item_tre
|
|||
}
|
||||
|
||||
using cbindgen_private::FocusEvent;
|
||||
using cbindgen_private::FocusEventResult;
|
||||
using cbindgen_private::InputEventResult;
|
||||
using cbindgen_private::KeyEvent;
|
||||
using cbindgen_private::KeyEventResult;
|
||||
|
@ -177,8 +177,7 @@ namespace private_api {
|
|||
template<typename GetDynamic>
|
||||
inline InputEventResult process_input_event(const ComponentRc &component_rc, int64_t &mouse_grabber,
|
||||
MouseEvent mouse_event, Slice<ItemTreeNode> tree,
|
||||
GetDynamic get_dynamic, const ComponentWindow *window,
|
||||
const ComponentRef *app_component)
|
||||
GetDynamic get_dynamic, const ComponentWindow *window)
|
||||
{
|
||||
if (mouse_grabber != -1) {
|
||||
auto item_index = mouse_grabber & 0xffffffff;
|
||||
|
@ -196,11 +195,11 @@ inline InputEventResult process_input_event(const ComponentRc &component_rc, int
|
|||
reinterpret_cast<char *>(component_rc.borrow().instance)
|
||||
+ item_node.item.item.offset,
|
||||
},
|
||||
mouse_event, window, *app_component);
|
||||
mouse_event, window, &component_rc, item_index);
|
||||
break;
|
||||
case ItemTreeNode::Tag::DynamicTree: {
|
||||
ComponentRef comp = get_dynamic(item_node.dynamic_tree.index, rep_index);
|
||||
result = comp.vtable->input_event(comp, mouse_event, window, app_component);
|
||||
result = comp.vtable->input_event(comp, mouse_event, window);
|
||||
} break;
|
||||
}
|
||||
if (result != InputEventResult::GrabMouse) {
|
||||
|
@ -208,80 +207,10 @@ inline InputEventResult process_input_event(const ComponentRc &component_rc, int
|
|||
}
|
||||
return result;
|
||||
} else {
|
||||
return cbindgen_private::sixtyfps_process_ungrabbed_mouse_event(
|
||||
&component_rc, mouse_event, window, *app_component, &mouse_grabber);
|
||||
return cbindgen_private::sixtyfps_process_ungrabbed_mouse_event(&component_rc, mouse_event,
|
||||
window, &mouse_grabber);
|
||||
}
|
||||
}
|
||||
template<typename GetDynamic>
|
||||
inline KeyEventResult process_key_event(ComponentRef component, int64_t focus_item,
|
||||
const KeyEvent *event, Slice<ItemTreeNode> tree,
|
||||
GetDynamic get_dynamic, const ComponentWindow *window)
|
||||
{
|
||||
if (focus_item != -1) {
|
||||
auto item_index = focus_item & 0xffffffff;
|
||||
auto rep_index = focus_item >> 32;
|
||||
const auto &item_node = tree.ptr[item_index];
|
||||
switch (item_node.tag) {
|
||||
case ItemTreeNode::Tag::Item:
|
||||
return item_node.item.item.vtable->key_event(
|
||||
{
|
||||
item_node.item.item.vtable,
|
||||
reinterpret_cast<char *>(component.instance)
|
||||
+ item_node.item.item.offset,
|
||||
},
|
||||
event, window);
|
||||
case ItemTreeNode::Tag::DynamicTree: {
|
||||
ComponentRef comp = get_dynamic(item_node.dynamic_tree.index, rep_index);
|
||||
return comp.vtable->key_event(comp, event, window);
|
||||
};
|
||||
}
|
||||
}
|
||||
return KeyEventResult::EventIgnored;
|
||||
}
|
||||
|
||||
template<typename GetDynamic>
|
||||
inline FocusEventResult process_focus_event(const ComponentRc &component_rc, int64_t &focus_item,
|
||||
const FocusEvent *event, Slice<ItemTreeNode> tree,
|
||||
GetDynamic get_dynamic, const ComponentWindow *window)
|
||||
{
|
||||
switch (event->tag) {
|
||||
case FocusEvent::Tag::FocusIn:
|
||||
return cbindgen_private::sixtyfps_locate_and_activate_focus_item(&component_rc, event,
|
||||
window, &focus_item);
|
||||
case FocusEvent::Tag::FocusOut:
|
||||
[[fallthrough]];
|
||||
case FocusEvent::Tag::WindowReceivedFocus:
|
||||
[[fallthrough]];
|
||||
case FocusEvent::Tag::WindowLostFocus:
|
||||
if (focus_item != -1) {
|
||||
auto item_index = focus_item & 0xffffffff;
|
||||
auto rep_index = focus_item >> 32;
|
||||
const auto &item_node = tree.ptr[item_index];
|
||||
switch (item_node.tag) {
|
||||
case ItemTreeNode::Tag::Item:
|
||||
item_node.item.item.vtable->focus_event(
|
||||
{
|
||||
item_node.item.item.vtable,
|
||||
reinterpret_cast<char *>(component_rc.borrow().instance)
|
||||
+ item_node.item.item.offset,
|
||||
},
|
||||
event, window);
|
||||
break;
|
||||
case ItemTreeNode::Tag::DynamicTree: {
|
||||
ComponentRef comp = get_dynamic(item_node.dynamic_tree.index, rep_index);
|
||||
comp.vtable->focus_event(comp, event, window);
|
||||
} break;
|
||||
}
|
||||
if (event->tag == FocusEvent::Tag::FocusOut) {
|
||||
focus_item = -1;
|
||||
}
|
||||
return FocusEventResult::FocusItemFound;
|
||||
} else {
|
||||
return FocusEventResult::FocusItemNotFound;
|
||||
}
|
||||
}
|
||||
return FocusEventResult::FocusItemNotFound;
|
||||
}
|
||||
|
||||
void dealloc(const ComponentVTable *, uint8_t *ptr, vtable::Layout layout)
|
||||
{
|
||||
|
|
|
@ -180,10 +180,9 @@ pub mod re_exports {
|
|||
PathArcTo, PathData, PathElement, PathEvent, PathLineTo, Point, Rect, Size,
|
||||
};
|
||||
pub use sixtyfps_corelib::input::{
|
||||
locate_and_activate_focus_item, process_ungrabbed_mouse_event, FocusEvent,
|
||||
FocusEventResult, InputEventResult, KeyCode, KeyEvent, KeyEventResult, KeyboardModifiers,
|
||||
MouseEvent, ALT_MODIFIER, CONTROL_MODIFIER, COPY_PASTE_MODIFIER, LOGO_MODIFIER,
|
||||
NO_MODIFIER, SHIFT_MODIFIER,
|
||||
process_ungrabbed_mouse_event, FocusEvent, InputEventResult, KeyCode, KeyEvent,
|
||||
KeyEventResult, KeyboardModifiers, MouseEvent, ALT_MODIFIER, CONTROL_MODIFIER,
|
||||
COPY_PASTE_MODIFIER, LOGO_MODIFIER, NO_MODIFIER, SHIFT_MODIFIER,
|
||||
};
|
||||
pub use sixtyfps_corelib::item_tree::{
|
||||
item_offset, visit_item_tree, ItemTreeNode, ItemVisitorRefMut, ItemVisitorVTable,
|
||||
|
|
|
@ -1104,7 +1104,7 @@ fn generate_component(
|
|||
Declaration::Function(Function {
|
||||
name: "input_event".into(),
|
||||
signature:
|
||||
"(sixtyfps::private_api::ComponentRef component, sixtyfps::MouseEvent mouse_event, const sixtyfps::private_api::ComponentWindow *window, const sixtyfps::private_api::ComponentRef *app_component) -> sixtyfps::InputEventResult"
|
||||
"(sixtyfps::private_api::ComponentRef component, sixtyfps::MouseEvent mouse_event, const sixtyfps::private_api::ComponentWindow *window) -> sixtyfps::InputEventResult"
|
||||
.into(),
|
||||
is_static: true,
|
||||
statements: Some(vec {".into(),
|
||||
" (void)self;".into(),
|
||||
format!(" switch(dyn_index) {{ {} }};", repeated_input_branch.join("")),
|
||||
" return sixtyfps::private_api::ComponentRef{nullptr, nullptr};\n}, window, app_component);".into(),
|
||||
]),
|
||||
..Default::default()
|
||||
}),
|
||||
));
|
||||
|
||||
component_struct.members.push((
|
||||
Access::Private,
|
||||
Declaration::Function(Function {
|
||||
name: "key_event".into(),
|
||||
signature:
|
||||
"(sixtyfps::private_api::ComponentRef component, const sixtyfps::KeyEvent *key_event, const sixtyfps::private_api::ComponentWindow *window) -> sixtyfps::KeyEventResult"
|
||||
.into(),
|
||||
is_static: true,
|
||||
statements: Some(vec {".into(),
|
||||
" (void)self;".into(),
|
||||
format!(" switch(dyn_index) {{ {} }};", repeated_input_branch.join("")),
|
||||
" return sixtyfps::private_api::ComponentRef{nullptr, nullptr};\n}, window);".into(),
|
||||
]),
|
||||
..Default::default()
|
||||
}),
|
||||
));
|
||||
|
||||
component_struct.members.push((
|
||||
Access::Private,
|
||||
Declaration::Var(Var {
|
||||
ty: "int64_t".into(),
|
||||
name: "focus_item".into(),
|
||||
init: Some("-1".into()),
|
||||
}),
|
||||
));
|
||||
component_struct.members.push((
|
||||
Access::Private,
|
||||
Declaration::Function(Function {
|
||||
name: "focus_event".into(),
|
||||
signature:
|
||||
"(sixtyfps::private_api::ComponentRef component, const sixtyfps::FocusEvent *focus_event, const sixtyfps::private_api::ComponentWindow *window) -> sixtyfps::FocusEventResult"
|
||||
.into(),
|
||||
is_static: true,
|
||||
statements: Some(vec {".into(),
|
||||
" (void)self;".into(),
|
||||
format!(" switch(dyn_index) {{ {} }};", repeated_input_branch.join("")),
|
||||
" return sixtyfps::private_api::ComponentRef{nullptr, nullptr};\n}, window);".into(),
|
||||
]),
|
||||
..Default::default()
|
||||
|
@ -1243,7 +1196,7 @@ fn generate_component(
|
|||
ty: "const sixtyfps::private_api::ComponentVTable".to_owned(),
|
||||
name: format!("{}::component_type", component_id),
|
||||
init: Some(format!(
|
||||
"{{ visit_children, get_item_ref, layouting_info, apply_layout, input_event, key_event, focus_event, sixtyfps::private_api::drop_in_place<{}>, sixtyfps::private_api::dealloc }}",
|
||||
"{{ visit_children, get_item_ref, layouting_info, apply_layout, input_event, sixtyfps::private_api::drop_in_place<{}>, sixtyfps::private_api::dealloc }}",
|
||||
component_id)
|
||||
),
|
||||
}));
|
||||
|
@ -1476,14 +1429,7 @@ fn compile_expression(e: &crate::expression_tree::Expression, component: &Rc<Com
|
|||
if let Expression::ElementReference(focus_item) = &arguments[0] {
|
||||
let focus_item = focus_item.upgrade().unwrap();
|
||||
let focus_item = focus_item.borrow();
|
||||
let component =
|
||||
format!("{{&{}::component_type, self}}", component_id(component));
|
||||
let item = format!(
|
||||
"{{&sixtyfps::private_api::{vt}, &self->{item}}}",
|
||||
vt = focus_item.base_type.as_native().vtable_symbol,
|
||||
item = focus_item.id
|
||||
);
|
||||
format!("self->window.set_focus_item({}, {});", component, item)
|
||||
format!("self->window.set_focus_item(self->self_weak.lock()->into_dyn(), {});", focus_item.item_index.get().unwrap())
|
||||
} else {
|
||||
panic!("internal error: argument to SetFocusItem must be an element")
|
||||
}
|
||||
|
|
|
@ -358,8 +358,6 @@ fn generate_component(
|
|||
let mut repeated_element_components = Vec::new();
|
||||
let mut repeated_visit_branch = Vec::new();
|
||||
let mut repeated_input_branch = Vec::new();
|
||||
let mut repeated_key_event_branch = Vec::new();
|
||||
let mut repeated_focus_branch = Vec::new();
|
||||
let mut init = Vec::new();
|
||||
let mut window_field_init = None;
|
||||
let mut window_parent_param = None;
|
||||
|
@ -524,13 +522,7 @@ fn generate_component(
|
|||
}
|
||||
|
||||
repeated_input_branch.push(quote!(
|
||||
#repeater_index => self.#repeater_id.input_event(rep_index, event, window, app_component),
|
||||
));
|
||||
repeated_key_event_branch.push(quote!(
|
||||
#repeater_index => self.#repeater_id.key_event(rep_index, event, window),
|
||||
));
|
||||
repeated_focus_branch.push(quote!(
|
||||
#repeater_index => self.#repeater_id.focus_event(rep_index, event, window),
|
||||
#repeater_index => self.#repeater_id.input_event(rep_index, event, window),
|
||||
));
|
||||
|
||||
item_tree_array.push(quote!(
|
||||
|
@ -694,10 +686,10 @@ fn generate_component(
|
|||
}
|
||||
}
|
||||
|
||||
fn input_event(self: ::core::pin::Pin<&Self>, mouse_event : sixtyfps::re_exports::MouseEvent, window: &sixtyfps::re_exports::ComponentWindow,
|
||||
app_component: &::core::pin::Pin<sixtyfps::re_exports::VRef<sixtyfps::re_exports::ComponentVTable>>) -> sixtyfps::re_exports::InputEventResult {
|
||||
fn input_event(self: ::core::pin::Pin<&Self>, mouse_event : sixtyfps::re_exports::MouseEvent, window: &sixtyfps::re_exports::ComponentWindow) -> sixtyfps::re_exports::InputEventResult {
|
||||
use sixtyfps::re_exports::*;
|
||||
let mouse_grabber = self.mouse_grabber.get();
|
||||
let self_rc = VRc::into_dyn(self.as_ref().self_weak.get().unwrap().upgrade().unwrap());
|
||||
#[allow(unused)]
|
||||
let (status, new_grab) = if let Some((item_index, rep_index)) = mouse_grabber.aborted_indexes() {
|
||||
let tree = Self::item_tree();
|
||||
|
@ -706,7 +698,7 @@ fn generate_component(
|
|||
event.pos -= offset.to_vector();
|
||||
let res = match tree[item_index] {
|
||||
ItemTreeNode::Item { item, .. } => {
|
||||
item.apply_pin(self).as_ref().input_event(event, window, app_component.clone())
|
||||
item.apply_pin(self).as_ref().input_event(event, window, &self_rc, item_index)
|
||||
}
|
||||
ItemTreeNode::DynamicTree { index } => {
|
||||
match index {
|
||||
|
@ -720,72 +712,12 @@ fn generate_component(
|
|||
_ => (res, VisitChildrenResult::CONTINUE),
|
||||
}
|
||||
} else {
|
||||
process_ungrabbed_mouse_event(&VRc::into_dyn(self.as_ref().self_weak.get().unwrap().upgrade().unwrap()), mouse_event, window, app_component.clone())
|
||||
process_ungrabbed_mouse_event(&self_rc, mouse_event, window)
|
||||
};
|
||||
self.mouse_grabber.set(new_grab);
|
||||
status
|
||||
}
|
||||
|
||||
fn key_event(self: ::core::pin::Pin<&Self>, event : &sixtyfps::re_exports::KeyEvent, window: &sixtyfps::re_exports::ComponentWindow)
|
||||
-> sixtyfps::re_exports::KeyEventResult {
|
||||
use sixtyfps::re_exports::*;
|
||||
#[allow(unused)]
|
||||
if let Some((item_index, rep_index)) = self.focus_item.get().aborted_indexes() {
|
||||
let tree = Self::item_tree();
|
||||
match tree[item_index] {
|
||||
ItemTreeNode::Item { item, .. } => {
|
||||
item.apply_pin(self).as_ref().key_event(&event, window)
|
||||
}
|
||||
ItemTreeNode::DynamicTree { index } => {
|
||||
match index {
|
||||
#(#repeated_key_event_branch)*
|
||||
_ => panic!("invalid index {}", index),
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
KeyEventResult::EventIgnored
|
||||
}
|
||||
}
|
||||
|
||||
fn focus_event(self: ::core::pin::Pin<&Self>, event: &sixtyfps::re_exports::FocusEvent, window: &sixtyfps::re_exports::ComponentWindow)
|
||||
-> sixtyfps::re_exports::FocusEventResult {
|
||||
use sixtyfps::re_exports::*;
|
||||
#[allow(unused)]
|
||||
match event {
|
||||
FocusEvent::FocusIn(_) => {
|
||||
let (event_result, visit_result) = locate_and_activate_focus_item(&VRc::into_dyn(self.as_ref().self_weak.get().unwrap().upgrade().unwrap()), event, window);
|
||||
if event_result == FocusEventResult::FocusItemFound {
|
||||
self.focus_item.set(visit_result)
|
||||
}
|
||||
event_result
|
||||
}
|
||||
FocusEvent::FocusOut | FocusEvent::WindowReceivedFocus | FocusEvent::WindowLostFocus => {
|
||||
if let Some((item_index, rep_index)) = self.focus_item.get().aborted_indexes() {
|
||||
let tree = Self::item_tree();
|
||||
match tree[item_index] {
|
||||
ItemTreeNode::Item { item, .. } => {
|
||||
item.apply_pin(self).as_ref().focus_event(&event, window)
|
||||
}
|
||||
ItemTreeNode::DynamicTree { index } => {
|
||||
match index {
|
||||
#(#repeated_focus_branch)*
|
||||
_ => panic!("invalid index {}", index),
|
||||
};
|
||||
}
|
||||
};
|
||||
// Preserve the focus_item field unless we're clearing it as part of a focus out phase.
|
||||
if matches!(event, FocusEvent::FocusOut) {
|
||||
self.focus_item.set(VisitChildrenResult::CONTINUE);
|
||||
}
|
||||
FocusEventResult::FocusItemFound // We had a focus item and "found" it and notified it
|
||||
} else {
|
||||
FocusEventResult::FocusItemNotFound
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#layouts
|
||||
|
||||
fn get_item_ref(self: ::core::pin::Pin<&Self>, index: usize) -> ::core::pin::Pin<ItemRef> {
|
||||
|
@ -842,7 +774,6 @@ fn generate_component(
|
|||
#(#self_weak : sixtyfps::re_exports::OnceCell<sixtyfps::re_exports::VWeak<sixtyfps::re_exports::ComponentVTable, #component_id>>,)*
|
||||
#(parent : sixtyfps::re_exports::VWeak<sixtyfps::re_exports::ComponentVTable, #parent_component_type>,)*
|
||||
mouse_grabber: ::core::cell::Cell<sixtyfps::re_exports::VisitChildrenResult>,
|
||||
focus_item: ::core::cell::Cell<sixtyfps::re_exports::VisitChildrenResult>,
|
||||
#(#global_name : ::core::pin::Pin<::std::rc::Rc<#global_type>>,)*
|
||||
#window_field
|
||||
}
|
||||
|
@ -863,7 +794,6 @@ fn generate_component(
|
|||
#(#self_weak : ::core::default::Default::default(),)*
|
||||
#(parent : parent as sixtyfps::re_exports::VWeak::<sixtyfps::re_exports::ComponentVTable, #parent_component_type>,)*
|
||||
mouse_grabber: ::core::cell::Cell::new(sixtyfps::re_exports::VisitChildrenResult::CONTINUE),
|
||||
focus_item: ::core::cell::Cell::new(sixtyfps::re_exports::VisitChildrenResult::CONTINUE),
|
||||
#(#global_name : #global_type::new(),)*
|
||||
#window_field_init
|
||||
};
|
||||
|
@ -1129,9 +1059,11 @@ fn compile_expression(e: &Expression, component: &Rc<Component>) -> TokenStream
|
|||
panic!("internal error: incorrect argument count to SetFocusItem call");
|
||||
}
|
||||
if let Expression::ElementReference(focus_item) = &arguments[0] {
|
||||
let item = format_ident!("{}", focus_item.upgrade().unwrap().borrow().id);
|
||||
let focus_item = focus_item.upgrade().unwrap();
|
||||
let focus_item = focus_item.borrow();
|
||||
let item_index = focus_item.item_index.get().unwrap();
|
||||
quote!(
|
||||
_self.window.set_focus_item(VRef::new_pin(self_pinned.as_pin_ref()), VRef::new_pin(Self::FIELD_OFFSETS.#item.apply_pin(self_pinned.as_pin_ref())));
|
||||
_self.window.set_focus_item(&VRc::into_dyn(_self.self_weak.get().unwrap().upgrade().unwrap()), #item_index);
|
||||
)
|
||||
} else {
|
||||
panic!("internal error: argument to SetFocusItem must be an element")
|
||||
|
|
|
@ -165,6 +165,25 @@ pub async fn run_passes<'a>(
|
|||
passes::resolve_native_classes::resolve_native_classes(&doc.root_component);
|
||||
passes::collect_globals::collect_globals(&doc.root_component, diag);
|
||||
passes::collect_structs::collect_structs(&doc.root_component, diag);
|
||||
|
||||
fn generate_item_indices(component: &Rc<object_tree::Component>) {
|
||||
let mut current_item_index: usize = 0;
|
||||
generator::build_array_helper(&component, move |item_rc, _, is_flickable_rect| {
|
||||
let item = item_rc.borrow();
|
||||
if is_flickable_rect {
|
||||
current_item_index += 1;
|
||||
} else if item.base_type == crate::langtype::Type::Void {
|
||||
} else if item.repeated.is_some() {
|
||||
generate_item_indices(&*item.base_type.as_component());
|
||||
current_item_index += 1;
|
||||
} else {
|
||||
item.item_index.set(current_item_index).unwrap();
|
||||
current_item_index += 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
generate_item_indices(&doc.root_component);
|
||||
}
|
||||
|
||||
mod library {
|
||||
|
|
|
@ -268,6 +268,10 @@ pub struct Element {
|
|||
|
||||
pub child_of_layout: bool,
|
||||
|
||||
/// This is the component-local index of this item in the item tree array.
|
||||
/// It is generated after the last pass and before the generators run.
|
||||
pub item_index: once_cell::unsync::OnceCell<usize>,
|
||||
|
||||
/// The AST node, if available
|
||||
pub node: Option<syntax_nodes::Element>,
|
||||
}
|
||||
|
|
|
@ -167,6 +167,7 @@ fn duplicate_element_with_mapping(
|
|||
.map(|t| duplicate_transition(t, mapping, root_component))
|
||||
.collect(),
|
||||
child_of_layout: elem.child_of_layout,
|
||||
item_index: Default::default(), // Not determined yet
|
||||
}));
|
||||
mapping.insert(element_key(element.clone()), new.clone());
|
||||
new
|
||||
|
|
|
@ -46,6 +46,7 @@ fn create_repeater_components(component: &Rc<Component>) {
|
|||
states: std::mem::take(&mut elem.states),
|
||||
transitions: std::mem::take(&mut elem.transitions),
|
||||
child_of_layout: elem.child_of_layout,
|
||||
item_index: Default::default(), // Not determined yet
|
||||
})),
|
||||
parent_element,
|
||||
..Component::default()
|
||||
|
|
|
@ -13,9 +13,7 @@ LICENSE END */
|
|||
|
||||
use crate::eventloop::ComponentWindow;
|
||||
use crate::graphics::Rect;
|
||||
use crate::input::{
|
||||
FocusEvent, FocusEventResult, InputEventResult, KeyEvent, KeyEventResult, MouseEvent,
|
||||
};
|
||||
use crate::input::{InputEventResult, MouseEvent};
|
||||
use crate::item_tree::{ItemVisitorVTable, TraversalOrder, VisitChildrenResult};
|
||||
use crate::items::ItemVTable;
|
||||
use crate::layout::LayoutInfo;
|
||||
|
@ -52,23 +50,8 @@ pub struct ComponentVTable {
|
|||
core::pin::Pin<VRef<ComponentVTable>>,
|
||||
MouseEvent,
|
||||
&ComponentWindow,
|
||||
&core::pin::Pin<VRef<ComponentVTable>>,
|
||||
) -> InputEventResult,
|
||||
|
||||
/// key event
|
||||
pub key_event: extern "C" fn(
|
||||
core::pin::Pin<VRef<ComponentVTable>>,
|
||||
&KeyEvent,
|
||||
&ComponentWindow,
|
||||
) -> KeyEventResult,
|
||||
|
||||
/// Event sent to transfer focus between items or to communicate window focus change.
|
||||
pub focus_event: extern "C" fn(
|
||||
core::pin::Pin<VRef<ComponentVTable>>,
|
||||
&FocusEvent,
|
||||
&ComponentWindow,
|
||||
) -> FocusEventResult,
|
||||
|
||||
/// in-place destructor (for VRc)
|
||||
pub drop_in_place: unsafe fn(VRefMut<ComponentVTable>) -> vtable::Layout,
|
||||
/// dealloc function (for VRc)
|
||||
|
|
|
@ -13,18 +13,13 @@ LICENSE END */
|
|||
[GenericWindow] trait used by the generated code and the run-time to change
|
||||
aspects of windows on the screen.
|
||||
*/
|
||||
use crate::{
|
||||
component::{ComponentRc, ComponentVTable},
|
||||
items::ItemRef,
|
||||
slice::Slice,
|
||||
};
|
||||
use crate::{component::ComponentRc, items::ItemRef, slice::Slice};
|
||||
use std::cell::RefCell;
|
||||
use std::{
|
||||
convert::TryInto,
|
||||
pin::Pin,
|
||||
rc::{Rc, Weak},
|
||||
};
|
||||
use vtable::*;
|
||||
|
||||
use crate::input::{KeyEvent, MouseEventType};
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
|
@ -107,11 +102,7 @@ pub trait GenericWindow {
|
|||
|
||||
/// Sets the focus to the item pointed to by item_ptr. This will remove the focus from any
|
||||
/// currently focused item.
|
||||
fn set_focus_item(
|
||||
self: Rc<Self>,
|
||||
component: core::pin::Pin<crate::component::ComponentRef>,
|
||||
item_ptr: *const u8,
|
||||
);
|
||||
fn set_focus_item(self: Rc<Self>, focus_item_component: &ComponentRc, focus_item_index: usize);
|
||||
/// Sets the focus on the window to true or false, depending on the have_focus argument.
|
||||
/// This results in WindowFocusReceived and WindowFocusLost events.
|
||||
fn set_focus(self: Rc<Self>, have_focus: bool);
|
||||
|
@ -181,12 +172,8 @@ impl ComponentWindow {
|
|||
|
||||
/// Clears the focus on any previously focused item and makes the provided
|
||||
/// item the focus item, in order to receive future key events.
|
||||
pub fn set_focus_item(
|
||||
&self,
|
||||
component: core::pin::Pin<crate::component::ComponentRef>,
|
||||
item: Pin<VRef<crate::items::ItemVTable>>,
|
||||
) {
|
||||
self.0.clone().set_focus_item(component, item.as_ptr())
|
||||
pub fn set_focus_item(&self, focus_item_component: &ComponentRc, focus_item_index: usize) {
|
||||
self.0.clone().set_focus_item(focus_item_component, focus_item_index)
|
||||
}
|
||||
|
||||
/// Associates this window with the specified component, for future event handling, etc.
|
||||
|
@ -532,7 +519,6 @@ pub mod ffi {
|
|||
#![allow(unsafe_code)]
|
||||
|
||||
use super::*;
|
||||
use crate::items::ItemVTable;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
type c_void = ();
|
||||
|
@ -609,11 +595,11 @@ pub mod ffi {
|
|||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_component_window_set_focus_item(
|
||||
handle: *const ComponentWindowOpaque,
|
||||
component: Pin<VRef<ComponentVTable>>,
|
||||
item: Pin<VRef<ItemVTable>>,
|
||||
focus_item_component: &ComponentRc,
|
||||
focus_item_index: usize,
|
||||
) {
|
||||
let window = &*(handle as *const ComponentWindow);
|
||||
window.set_focus_item(component, item)
|
||||
window.set_focus_item(focus_item_component, focus_item_index)
|
||||
}
|
||||
|
||||
/// Associates the window with the given component.
|
||||
|
|
|
@ -526,6 +526,8 @@ pub struct GraphicsWindow<Backend: GraphicsBackend + 'static> {
|
|||
keyboard_modifiers: std::cell::Cell<KeyboardModifiers>,
|
||||
component: std::cell::RefCell<ComponentWeak>,
|
||||
layout_listener: Pin<Rc<PropertyTracker>>,
|
||||
focus_item_component: std::cell::RefCell<ComponentWeak>,
|
||||
focus_item_index: std::cell::Cell<usize>,
|
||||
}
|
||||
|
||||
impl<Backend: GraphicsBackend + 'static> GraphicsWindow<Backend> {
|
||||
|
@ -547,6 +549,8 @@ impl<Backend: GraphicsBackend + 'static> GraphicsWindow<Backend> {
|
|||
keyboard_modifiers: Default::default(),
|
||||
component: Default::default(),
|
||||
layout_listener: Rc::pin(Default::default()),
|
||||
focus_item_component: Default::default(),
|
||||
focus_item_index: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -631,7 +635,7 @@ impl<Backend: GraphicsBackend> crate::eventloop::GenericWindow for GraphicsWindo
|
|||
crate::item_tree::visit_items(
|
||||
&component_rc,
|
||||
crate::item_tree::TraversalOrder::BackToFront,
|
||||
|_, item, _| {
|
||||
|_, item, _, _| {
|
||||
crate::item_rendering::update_item_rendering_data(
|
||||
item,
|
||||
&window.rendering_cache,
|
||||
|
@ -674,15 +678,17 @@ impl<Backend: GraphicsBackend> crate::eventloop::GenericWindow for GraphicsWindo
|
|||
component.as_ref().input_event(
|
||||
MouseEvent { pos: euclid::point2(pos.x as _, pos.y as _), what },
|
||||
&crate::eventloop::ComponentWindow::new(self.clone()),
|
||||
&component,
|
||||
);
|
||||
}
|
||||
|
||||
fn process_key_input(self: Rc<Self>, event: &KeyEvent) {
|
||||
let component = self.component.borrow().upgrade().unwrap();
|
||||
ComponentRc::borrow_pin(&component)
|
||||
.as_ref()
|
||||
.key_event(event, &crate::eventloop::ComponentWindow::new(self.clone()));
|
||||
if let Some(focus_item_component) = self.as_ref().focus_item_component.borrow().upgrade() {
|
||||
let window = &crate::eventloop::ComponentWindow::new(self.clone());
|
||||
let comp_ref_pin = ComponentRc::borrow_pin(&focus_item_component);
|
||||
let focus_item =
|
||||
comp_ref_pin.as_ref().get_item_ref(self.as_ref().focus_item_index.get() as usize);
|
||||
focus_item.as_ref().key_event(event, &window);
|
||||
}
|
||||
}
|
||||
|
||||
fn with_platform_window(&self, callback: &dyn Fn(&winit::window::Window)) {
|
||||
|
@ -855,14 +861,25 @@ impl<Backend: GraphicsBackend> crate::eventloop::GenericWindow for GraphicsWindo
|
|||
self.keyboard_modifiers.set(state)
|
||||
}
|
||||
|
||||
fn set_focus_item(
|
||||
self: Rc<Self>,
|
||||
component: core::pin::Pin<crate::component::ComponentRef>,
|
||||
item_ptr: *const u8,
|
||||
) {
|
||||
fn set_focus_item(self: Rc<Self>, focus_item_component: &ComponentRc, focus_item_index: usize) {
|
||||
let window = crate::eventloop::ComponentWindow::new(self.clone());
|
||||
component.as_ref().focus_event(&crate::input::FocusEvent::FocusOut, &window);
|
||||
component.as_ref().focus_event(&crate::input::FocusEvent::FocusIn(item_ptr), &window);
|
||||
|
||||
if let Some(old_focus_item_component) =
|
||||
self.as_ref().focus_item_component.borrow().upgrade()
|
||||
{
|
||||
let comp_ref_pin = ComponentRc::borrow_pin(&old_focus_item_component);
|
||||
let old_focus_item =
|
||||
comp_ref_pin.as_ref().get_item_ref(self.as_ref().focus_item_index.get());
|
||||
old_focus_item.as_ref().focus_event(&crate::input::FocusEvent::FocusOut, &window);
|
||||
}
|
||||
|
||||
*self.as_ref().focus_item_component.borrow_mut() =
|
||||
ComponentRc::downgrade(&focus_item_component);
|
||||
self.as_ref().focus_item_index.set(focus_item_index);
|
||||
|
||||
let comp_ref_pin = ComponentRc::borrow_pin(&focus_item_component);
|
||||
let new_focus_item = comp_ref_pin.as_ref().get_item_ref(focus_item_index);
|
||||
new_focus_item.as_ref().focus_event(&crate::input::FocusEvent::FocusIn, &window);
|
||||
}
|
||||
|
||||
fn set_focus(self: Rc<Self>, have_focus: bool) {
|
||||
|
@ -872,8 +889,13 @@ impl<Backend: GraphicsBackend> crate::eventloop::GenericWindow for GraphicsWindo
|
|||
} else {
|
||||
crate::input::FocusEvent::WindowLostFocus
|
||||
};
|
||||
let component = self.component.borrow().upgrade().unwrap();
|
||||
ComponentRc::borrow_pin(&component).as_ref().focus_event(&event, &window);
|
||||
|
||||
if let Some(focus_item_component) = self.as_ref().focus_item_component.borrow().upgrade() {
|
||||
let comp_ref_pin = ComponentRc::borrow_pin(&focus_item_component);
|
||||
let focus_item =
|
||||
comp_ref_pin.as_ref().get_item_ref(self.as_ref().focus_item_index.get() as usize);
|
||||
focus_item.as_ref().focus_event(&event, &window);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ LICENSE END */
|
|||
*/
|
||||
#![warn(missing_docs)]
|
||||
|
||||
use crate::component::{ComponentRc, ComponentRefPin};
|
||||
use crate::component::ComponentRc;
|
||||
use crate::graphics::Point;
|
||||
use crate::item_tree::{ItemVisitorResult, VisitChildrenResult};
|
||||
use euclid::default::Vector2D;
|
||||
|
@ -453,10 +453,8 @@ pub enum KeyEventResult {
|
|||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[repr(C)]
|
||||
pub enum FocusEvent {
|
||||
/// This event is sent when an item receives the focus. The value contained
|
||||
/// in the tuple is a raw pointer to the item that is intended to receive the
|
||||
/// focus. This is only used for equality comparison.
|
||||
FocusIn(*const u8),
|
||||
/// This event is sent when an item receives the focus.
|
||||
FocusIn,
|
||||
/// This event is sent when an item looses the focus.
|
||||
FocusOut,
|
||||
/// This event is sent when the window receives the keyboard focus.
|
||||
|
@ -465,52 +463,6 @@ pub enum FocusEvent {
|
|||
WindowLostFocus,
|
||||
}
|
||||
|
||||
/// Represents how a component's focus_event dealt with the transfer of focus
|
||||
/// to an item.
|
||||
#[derive(Debug, Clone, PartialEq, Copy)]
|
||||
#[repr(C)]
|
||||
pub enum FocusEventResult {
|
||||
/// The requested item to transfer focus to was found.
|
||||
FocusItemFound,
|
||||
/// The requested focus item was not in the component's tree of items.
|
||||
FocusItemNotFound,
|
||||
}
|
||||
|
||||
/// Scans the tree of items of the component to locate the item pointed to by
|
||||
/// the focus_event (assuming it is of type FocusIn). Once located, the focus in
|
||||
/// even will also be dispatched to the item itself.
|
||||
pub fn locate_and_activate_focus_item(
|
||||
component: &ComponentRc,
|
||||
focus_event: &FocusEvent,
|
||||
window: &crate::eventloop::ComponentWindow,
|
||||
) -> (FocusEventResult, VisitChildrenResult) {
|
||||
let mut result = FocusEventResult::FocusItemNotFound;
|
||||
let item_index = crate::item_tree::visit_items(
|
||||
component,
|
||||
crate::item_tree::TraversalOrder::FrontToBack,
|
||||
|_, item, _| -> ItemVisitorResult<()> {
|
||||
if let FocusEvent::FocusIn(new_focus_item_ptr) = focus_event {
|
||||
if item.as_ptr() == *new_focus_item_ptr {
|
||||
item.as_ref().focus_event(focus_event, window);
|
||||
result = FocusEventResult::FocusItemFound;
|
||||
return ItemVisitorResult::Abort;
|
||||
}
|
||||
}
|
||||
ItemVisitorResult::Continue(())
|
||||
},
|
||||
(),
|
||||
);
|
||||
|
||||
(
|
||||
result,
|
||||
if result == FocusEventResult::FocusItemFound {
|
||||
item_index
|
||||
} else {
|
||||
VisitChildrenResult::CONTINUE
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/// Feed the given mouse event into the tree of items that component holds. The
|
||||
/// event will be delivered to items in front first.
|
||||
///
|
||||
|
@ -525,7 +477,6 @@ pub fn process_ungrabbed_mouse_event(
|
|||
component: &ComponentRc,
|
||||
event: MouseEvent,
|
||||
window: &crate::eventloop::ComponentWindow,
|
||||
app_component: ComponentRefPin,
|
||||
) -> (InputEventResult, VisitChildrenResult) {
|
||||
let offset = Vector2D::new(0., 0.);
|
||||
|
||||
|
@ -533,14 +484,14 @@ pub fn process_ungrabbed_mouse_event(
|
|||
let item_index = crate::item_tree::visit_items(
|
||||
component,
|
||||
crate::item_tree::TraversalOrder::FrontToBack,
|
||||
|_, item, offset| -> ItemVisitorResult<Vector2D<f32>> {
|
||||
|comp_rc, item, item_index, offset| -> ItemVisitorResult<Vector2D<f32>> {
|
||||
let geom = item.as_ref().geometry();
|
||||
let geom = geom.translate(*offset);
|
||||
|
||||
if geom.contains(event.pos) {
|
||||
let mut event2 = event.clone();
|
||||
event2.pos -= geom.origin.to_vector();
|
||||
match item.as_ref().input_event(event2, window, app_component) {
|
||||
match item.as_ref().input_event(event2, window, comp_rc, item_index) {
|
||||
InputEventResult::EventAccepted => {
|
||||
result = InputEventResult::EventAccepted;
|
||||
return ItemVisitorResult::Abort;
|
||||
|
@ -599,10 +550,9 @@ pub(crate) mod ffi {
|
|||
component: &ComponentRc,
|
||||
event: MouseEvent,
|
||||
window: &crate::eventloop::ComponentWindow,
|
||||
app_component: core::pin::Pin<crate::component::ComponentRef>,
|
||||
new_mouse_grabber: &mut crate::item_tree::VisitChildrenResult,
|
||||
) -> InputEventResult {
|
||||
let (res, grab) = process_ungrabbed_mouse_event(component, event, window, app_component);
|
||||
let (res, grab) = process_ungrabbed_mouse_event(component, event, window);
|
||||
*new_mouse_grabber = grab;
|
||||
res
|
||||
}
|
||||
|
@ -617,16 +567,4 @@ pub(crate) mod ffi {
|
|||
) -> (InputEventResult, crate::item_tree::VisitChildrenResult) {
|
||||
process_grabbed_mouse_event(component, item, offset, event, old_grab)
|
||||
}*/
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn sixtyfps_locate_and_activate_focus_item(
|
||||
component: &ComponentRc,
|
||||
event: &FocusEvent,
|
||||
window: &crate::eventloop::ComponentWindow,
|
||||
new_focus_item: &mut crate::item_tree::VisitChildrenResult,
|
||||
) -> FocusEventResult {
|
||||
let (result, focus_item) = locate_and_activate_focus_item(component, event, window);
|
||||
*new_focus_item = focus_item;
|
||||
result
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ pub(crate) fn render_component_items<Backend: GraphicsBackend>(
|
|||
crate::item_tree::visit_items_with_post_visit(
|
||||
component,
|
||||
crate::item_tree::TraversalOrder::BackToFront,
|
||||
|_, item, transform| {
|
||||
|_, item, _, transform| {
|
||||
let origin = item.as_ref().geometry().origin;
|
||||
let transform =
|
||||
transform * Matrix4::from_translation(Vector3::new(origin.x, origin.y, 0.));
|
||||
|
|
|
@ -140,13 +140,13 @@ pub enum ItemVisitorResult<State> {
|
|||
pub fn visit_items<State>(
|
||||
component: &ComponentRc,
|
||||
order: TraversalOrder,
|
||||
mut visitor: impl FnMut(&ComponentRc, Pin<ItemRef>, &State) -> ItemVisitorResult<State>,
|
||||
mut visitor: impl FnMut(&ComponentRc, Pin<ItemRef>, usize, &State) -> ItemVisitorResult<State>,
|
||||
state: State,
|
||||
) -> VisitChildrenResult {
|
||||
visit_internal(
|
||||
component,
|
||||
order,
|
||||
&mut |component, item, state| (visitor(component, item, state), ()),
|
||||
&mut |component, item, index, state| (visitor(component, item, index, state), ()),
|
||||
&mut |_, _, _| {},
|
||||
-1,
|
||||
&state,
|
||||
|
@ -164,6 +164,7 @@ pub fn visit_items_with_post_visit<State, PostVisitState>(
|
|||
mut visitor: impl FnMut(
|
||||
&ComponentRc,
|
||||
Pin<ItemRef>,
|
||||
usize,
|
||||
&State,
|
||||
) -> (ItemVisitorResult<State>, PostVisitState),
|
||||
mut post_visitor: impl FnMut(&ComponentRc, Pin<ItemRef>, PostVisitState),
|
||||
|
@ -178,6 +179,7 @@ fn visit_internal<State, PostVisitState>(
|
|||
visitor: &mut impl FnMut(
|
||||
&ComponentRc,
|
||||
Pin<ItemRef>,
|
||||
usize,
|
||||
&State,
|
||||
) -> (ItemVisitorResult<State>, PostVisitState),
|
||||
post_visitor: &mut impl FnMut(&ComponentRc, Pin<ItemRef>, PostVisitState),
|
||||
|
@ -188,7 +190,7 @@ fn visit_internal<State, PostVisitState>(
|
|||
index: usize,
|
||||
item: Pin<ItemRef>|
|
||||
-> VisitChildrenResult {
|
||||
match visitor(component, item, state) {
|
||||
match visitor(component, item, index, state) {
|
||||
(ItemVisitorResult::Continue(state), post_visit_state) => {
|
||||
let result =
|
||||
visit_internal(component, order, visitor, post_visitor, index as isize, &state);
|
||||
|
|
|
@ -25,7 +25,7 @@ When adding an item or a property, it needs to be kept in sync with different pl
|
|||
#![allow(non_upper_case_globals)]
|
||||
#![allow(missing_docs)] // because documenting each property of items is redundent
|
||||
|
||||
use super::component::{ComponentRefPin, ComponentVTable};
|
||||
use super::component::ComponentVTable;
|
||||
use super::eventloop::ComponentWindow;
|
||||
use super::graphics::{Color, HighLevelRenderingPrimitive, PathData, Rect, Resource};
|
||||
use super::input::{
|
||||
|
@ -84,7 +84,8 @@ pub struct ItemVTable {
|
|||
core::pin::Pin<VRef<ItemVTable>>,
|
||||
MouseEvent,
|
||||
window: &ComponentWindow,
|
||||
app_component: core::pin::Pin<VRef<ComponentVTable>>,
|
||||
self_component: &VRc<ComponentVTable, vtable::Dyn>,
|
||||
self_index: usize,
|
||||
) -> InputEventResult,
|
||||
|
||||
pub focus_event:
|
||||
|
@ -160,7 +161,8 @@ impl Item for Rectangle {
|
|||
self: Pin<&Self>,
|
||||
_: MouseEvent,
|
||||
_window: &ComponentWindow,
|
||||
_app_component: ComponentRefPin,
|
||||
_self_component: &VRc<ComponentVTable, vtable::Dyn>,
|
||||
_self_index: usize,
|
||||
) -> InputEventResult {
|
||||
InputEventResult::EventIgnored
|
||||
}
|
||||
|
@ -248,7 +250,8 @@ impl Item for BorderRectangle {
|
|||
self: Pin<&Self>,
|
||||
_: MouseEvent,
|
||||
_window: &ComponentWindow,
|
||||
_app_component: ComponentRefPin,
|
||||
_self_component: &VRc<ComponentVTable, vtable::Dyn>,
|
||||
_self_index: usize,
|
||||
) -> InputEventResult {
|
||||
InputEventResult::EventIgnored
|
||||
}
|
||||
|
@ -334,7 +337,8 @@ impl Item for Image {
|
|||
self: Pin<&Self>,
|
||||
_: MouseEvent,
|
||||
_window: &ComponentWindow,
|
||||
_app_component: ComponentRefPin,
|
||||
_self_component: &VRc<ComponentVTable, vtable::Dyn>,
|
||||
_self_index: usize,
|
||||
) -> InputEventResult {
|
||||
InputEventResult::EventIgnored
|
||||
}
|
||||
|
@ -476,7 +480,8 @@ impl Item for Text {
|
|||
self: Pin<&Self>,
|
||||
_: MouseEvent,
|
||||
_window: &ComponentWindow,
|
||||
_app_component: ComponentRefPin,
|
||||
_self_component: &VRc<ComponentVTable, vtable::Dyn>,
|
||||
_self_index: usize,
|
||||
) -> InputEventResult {
|
||||
InputEventResult::EventIgnored
|
||||
}
|
||||
|
@ -567,7 +572,8 @@ impl Item for TouchArea {
|
|||
self: Pin<&Self>,
|
||||
event: MouseEvent,
|
||||
_window: &ComponentWindow,
|
||||
_app_component: ComponentRefPin,
|
||||
_self_component: &VRc<ComponentVTable, vtable::Dyn>,
|
||||
_self_index: usize,
|
||||
) -> InputEventResult {
|
||||
Self::FIELD_OFFSETS.mouse_x.apply_pin(self).set(event.pos.x);
|
||||
Self::FIELD_OFFSETS.mouse_y.apply_pin(self).set(event.pos.y);
|
||||
|
@ -674,7 +680,8 @@ impl Item for Path {
|
|||
self: Pin<&Self>,
|
||||
_: MouseEvent,
|
||||
_window: &ComponentWindow,
|
||||
_app_component: ComponentRefPin,
|
||||
_self_component: &VRc<ComponentVTable, vtable::Dyn>,
|
||||
_self_index: usize,
|
||||
) -> InputEventResult {
|
||||
InputEventResult::EventIgnored
|
||||
}
|
||||
|
@ -750,7 +757,8 @@ impl Item for Flickable {
|
|||
self: Pin<&Self>,
|
||||
event: MouseEvent,
|
||||
_window: &ComponentWindow,
|
||||
_app_component: ComponentRefPin,
|
||||
_self_component: &VRc<ComponentVTable, vtable::Dyn>,
|
||||
_self_index: usize,
|
||||
) -> InputEventResult {
|
||||
if !Self::FIELD_OFFSETS.interactive.apply_pin(self).get() {
|
||||
return InputEventResult::EventIgnored;
|
||||
|
@ -875,7 +883,8 @@ impl Item for Window {
|
|||
self: Pin<&Self>,
|
||||
_event: MouseEvent,
|
||||
_window: &ComponentWindow,
|
||||
_app_component: ComponentRefPin,
|
||||
_self_component: &VRc<ComponentVTable, vtable::Dyn>,
|
||||
_self_index: usize,
|
||||
) -> InputEventResult {
|
||||
InputEventResult::EventIgnored
|
||||
}
|
||||
|
@ -1034,7 +1043,8 @@ impl Item for TextInput {
|
|||
self: Pin<&Self>,
|
||||
event: MouseEvent,
|
||||
window: &ComponentWindow,
|
||||
app_component: ComponentRefPin,
|
||||
self_component: &VRc<ComponentVTable, vtable::Dyn>,
|
||||
self_index: usize,
|
||||
) -> InputEventResult {
|
||||
if !Self::FIELD_OFFSETS.enabled.apply_pin(self).get() {
|
||||
return InputEventResult::EventIgnored;
|
||||
|
@ -1050,7 +1060,7 @@ impl Item for TextInput {
|
|||
self.as_ref().anchor_position.set(clicked_offset);
|
||||
self.as_ref().cursor_position.set(clicked_offset);
|
||||
if !Self::FIELD_OFFSETS.has_focus.apply_pin(self).get() {
|
||||
window.set_focus_item(app_component, VRef::new_pin(self));
|
||||
window.set_focus_item(self_component, self_index);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1166,7 +1176,7 @@ impl Item for TextInput {
|
|||
|
||||
fn focus_event(self: Pin<&Self>, event: &FocusEvent, window: &ComponentWindow) {
|
||||
match event {
|
||||
FocusEvent::FocusIn(_) | FocusEvent::WindowReceivedFocus => {
|
||||
FocusEvent::FocusIn | FocusEvent::WindowReceivedFocus => {
|
||||
self.has_focus.set(true);
|
||||
self.show_cursor(window);
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ use std::{
|
|||
rc::{Rc, Weak},
|
||||
};
|
||||
|
||||
use crate::component::ComponentRefPin;
|
||||
use crate::items::ItemRef;
|
||||
use crate::Property;
|
||||
|
||||
|
@ -562,36 +561,9 @@ impl<C: RepeatedComponent> Repeater<C> {
|
|||
idx: usize,
|
||||
event: crate::input::MouseEvent,
|
||||
window: &crate::eventloop::ComponentWindow,
|
||||
app_component: &ComponentRefPin,
|
||||
) -> crate::input::InputEventResult {
|
||||
let c = self.inner.borrow().borrow().components[idx].1.clone();
|
||||
c.map_or(Default::default(), |c| c.as_pin_ref().input_event(event, window, app_component))
|
||||
}
|
||||
|
||||
/// Forward a key event to a particular item
|
||||
pub fn key_event(
|
||||
&self,
|
||||
idx: usize,
|
||||
event: &crate::input::KeyEvent,
|
||||
window: &crate::eventloop::ComponentWindow,
|
||||
) -> crate::input::KeyEventResult {
|
||||
let c = self.inner.borrow().borrow().components[idx].1.clone();
|
||||
c.map_or(crate::input::KeyEventResult::EventIgnored, |c| {
|
||||
c.as_pin_ref().key_event(event, window)
|
||||
})
|
||||
}
|
||||
|
||||
/// Forward a focus event to a particular item
|
||||
pub fn focus_event(
|
||||
&self,
|
||||
idx: usize,
|
||||
event: &crate::input::FocusEvent,
|
||||
window: &crate::eventloop::ComponentWindow,
|
||||
) -> crate::input::FocusEventResult {
|
||||
let c = self.inner.borrow().borrow().components[idx].1.clone();
|
||||
c.map_or(crate::input::FocusEventResult::FocusItemNotFound, |c| {
|
||||
c.as_pin_ref().focus_event(event, window)
|
||||
})
|
||||
c.map_or(Default::default(), |c| c.as_pin_ref().input_event(event, window))
|
||||
}
|
||||
|
||||
/// Return the amount of item currently in the component
|
||||
|
|
|
@ -35,22 +35,10 @@ pub extern "C" fn sixtyfps_send_mouse_click(
|
|||
) {
|
||||
component.as_ref().apply_layout(window.0.get_geometry());
|
||||
let pos = euclid::point2(x, y);
|
||||
component.as_ref().input_event(
|
||||
MouseEvent { pos, what: MouseEventType::MouseMoved },
|
||||
window,
|
||||
&component,
|
||||
);
|
||||
component.as_ref().input_event(
|
||||
MouseEvent { pos, what: MouseEventType::MousePressed },
|
||||
window,
|
||||
&component,
|
||||
);
|
||||
component.as_ref().input_event(MouseEvent { pos, what: MouseEventType::MouseMoved }, window);
|
||||
component.as_ref().input_event(MouseEvent { pos, what: MouseEventType::MousePressed }, window);
|
||||
sixtyfps_mock_elapsed_time(50);
|
||||
component.as_ref().input_event(
|
||||
MouseEvent { pos, what: MouseEventType::MouseReleased },
|
||||
window,
|
||||
&component,
|
||||
);
|
||||
component.as_ref().input_event(MouseEvent { pos, what: MouseEventType::MouseReleased }, window);
|
||||
}
|
||||
|
||||
/// Simulate a change in keyboard modifiers pressed.
|
||||
|
|
|
@ -19,10 +19,9 @@ use sixtyfps_compilerlib::langtype::Type;
|
|||
use sixtyfps_compilerlib::layout::{Layout, LayoutConstraints, LayoutItem, PathLayout};
|
||||
use sixtyfps_compilerlib::*;
|
||||
use sixtyfps_corelib::component::{Component, ComponentRefPin, ComponentVTable};
|
||||
use sixtyfps_corelib::eventloop::ComponentWindow;
|
||||
use sixtyfps_corelib::graphics::{Rect, Resource};
|
||||
use sixtyfps_corelib::input::{
|
||||
FocusEventResult, InputEventResult, KeyEvent, KeyEventResult, MouseEvent,
|
||||
};
|
||||
use sixtyfps_corelib::input::{InputEventResult, MouseEvent};
|
||||
use sixtyfps_corelib::item_tree::{
|
||||
ItemTreeNode, ItemVisitorRefMut, ItemVisitorVTable, TraversalOrder, VisitChildrenResult,
|
||||
};
|
||||
|
@ -33,7 +32,6 @@ use sixtyfps_corelib::model::Repeater;
|
|||
use sixtyfps_corelib::properties::InterpolatedPropertyValue;
|
||||
use sixtyfps_corelib::rtti::{self, AnimatedBindingKind, FieldOffset, PropertyInfo};
|
||||
use sixtyfps_corelib::slice::Slice;
|
||||
use sixtyfps_corelib::{eventloop::ComponentWindow, input::FocusEvent};
|
||||
use sixtyfps_corelib::{Color, Property, SharedString, Signal};
|
||||
use std::collections::HashMap;
|
||||
use std::{pin::Pin, rc::Rc};
|
||||
|
@ -112,6 +110,10 @@ impl ItemWithinComponent {
|
|||
NonNull::new(mem.add(self.offset) as _).unwrap(),
|
||||
))
|
||||
}
|
||||
|
||||
pub(crate) fn item_index(&self) -> usize {
|
||||
*self.elem.borrow().item_index.get().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct PropertiesWithinComponent {
|
||||
|
@ -205,25 +207,8 @@ impl Component for ErasedComponentBox {
|
|||
self: Pin<&Self>,
|
||||
mouse_event: sixtyfps_corelib::input::MouseEvent,
|
||||
window: &ComponentWindow,
|
||||
app_component: &ComponentRefPin,
|
||||
) -> sixtyfps_corelib::input::InputEventResult {
|
||||
self.borrow().as_ref().input_event(mouse_event, window, app_component)
|
||||
}
|
||||
|
||||
fn key_event(
|
||||
self: Pin<&Self>,
|
||||
event: &sixtyfps_corelib::input::KeyEvent,
|
||||
window: &ComponentWindow,
|
||||
) -> sixtyfps_corelib::input::KeyEventResult {
|
||||
self.borrow().as_ref().key_event(event, window)
|
||||
}
|
||||
|
||||
fn focus_event(
|
||||
self: Pin<&Self>,
|
||||
event: &sixtyfps_corelib::input::FocusEvent,
|
||||
window: &ComponentWindow,
|
||||
) -> sixtyfps_corelib::input::FocusEventResult {
|
||||
self.borrow().as_ref().focus_event(event, window)
|
||||
self.borrow().as_ref().input_event(mouse_event, window)
|
||||
}
|
||||
|
||||
fn layout_info(self: Pin<&Self>) -> sixtyfps_corelib::layout::LayoutInfo {
|
||||
|
@ -244,7 +229,6 @@ sixtyfps_corelib::ComponentVTable_static!(static COMPONENT_BOX_VT for ErasedComp
|
|||
|
||||
pub(crate) struct ComponentExtraData {
|
||||
mouse_grabber: core::cell::Cell<VisitChildrenResult>,
|
||||
focus_item: core::cell::Cell<VisitChildrenResult>,
|
||||
pub(crate) globals: HashMap<String, Pin<Rc<dyn crate::global_component::GlobalComponent>>>,
|
||||
pub(crate) self_weak:
|
||||
once_cell::unsync::OnceCell<vtable::VWeak<ComponentVTable, ErasedComponentBox>>,
|
||||
|
@ -254,7 +238,6 @@ impl Default for ComponentExtraData {
|
|||
fn default() -> Self {
|
||||
Self {
|
||||
mouse_grabber: core::cell::Cell::new(VisitChildrenResult::CONTINUE),
|
||||
focus_item: core::cell::Cell::new(VisitChildrenResult::CONTINUE),
|
||||
globals: HashMap::new(),
|
||||
self_weak: Default::default(),
|
||||
}
|
||||
|
@ -703,8 +686,6 @@ fn generate_component<'id>(
|
|||
layout_info,
|
||||
apply_layout,
|
||||
input_event,
|
||||
key_event,
|
||||
focus_event,
|
||||
get_item_ref,
|
||||
drop_in_place,
|
||||
dealloc,
|
||||
|
@ -1462,33 +1443,32 @@ extern "C" fn input_event(
|
|||
component: ComponentRefPin,
|
||||
mouse_event: sixtyfps_corelib::input::MouseEvent,
|
||||
window: &sixtyfps_corelib::eventloop::ComponentWindow,
|
||||
app_component: &ComponentRefPin,
|
||||
) -> sixtyfps_corelib::input::InputEventResult {
|
||||
// This is fine since we can only be called with a component that with our vtable which is a ComponentDescription
|
||||
let component_type = unsafe { get_component_type(component) };
|
||||
let instance = unsafe { Pin::new_unchecked(&*component.as_ptr().cast::<Instance>()) };
|
||||
let extra_data = component_type.extra_data_offset.apply(&*instance);
|
||||
generativity::make_guard!(guard);
|
||||
let instance_ref = unsafe { InstanceRef::from_pin_ref(component, guard) };
|
||||
let comp_rc = instance_ref.self_weak().get().unwrap().upgrade().unwrap();
|
||||
|
||||
let mouse_grabber = extra_data.mouse_grabber.get();
|
||||
let (status, new_grab) = if let Some((item_index, rep_index)) = mouse_grabber.aborted_indexes()
|
||||
{
|
||||
let (status, new_grab) =
|
||||
if let Some((item_index, rep_index)) = mouse_grabber.aborted_indexes() {
|
||||
let tree = &component_type.item_tree;
|
||||
let offset = sixtyfps_corelib::item_tree::item_offset(instance, tree, item_index);
|
||||
let mut event = mouse_event.clone();
|
||||
event.pos -= offset.to_vector();
|
||||
let res = match tree[item_index] {
|
||||
ItemTreeNode::Item { item, .. } => {
|
||||
item.apply_pin(instance).as_ref().input_event(event, window, app_component.clone())
|
||||
}
|
||||
let res =
|
||||
match tree[item_index] {
|
||||
ItemTreeNode::Item { item, .. } => item
|
||||
.apply_pin(instance)
|
||||
.as_ref()
|
||||
.input_event(event, window, &vtable::VRc::into_dyn(comp_rc), item_index),
|
||||
ItemTreeNode::DynamicTree { index } => {
|
||||
generativity::make_guard!(guard);
|
||||
let rep_in_comp = component_type.repeater[index].unerase(guard);
|
||||
rep_in_comp.offset.apply_pin(instance).input_event(
|
||||
rep_index,
|
||||
event,
|
||||
window,
|
||||
app_component,
|
||||
)
|
||||
rep_in_comp.offset.apply_pin(instance).input_event(rep_index, event, window)
|
||||
}
|
||||
};
|
||||
match res {
|
||||
|
@ -1496,102 +1476,16 @@ extern "C" fn input_event(
|
|||
_ => (res, VisitChildrenResult::CONTINUE),
|
||||
}
|
||||
} else {
|
||||
generativity::make_guard!(guard);
|
||||
let instance_ref = unsafe { InstanceRef::from_pin_ref(component, guard) };
|
||||
let comp_rc = instance_ref.self_weak().get().unwrap().upgrade().unwrap();
|
||||
|
||||
sixtyfps_corelib::input::process_ungrabbed_mouse_event(
|
||||
&vtable::VRc::into_dyn(comp_rc),
|
||||
mouse_event,
|
||||
window,
|
||||
app_component.clone(),
|
||||
)
|
||||
};
|
||||
extra_data.mouse_grabber.set(new_grab);
|
||||
status
|
||||
}
|
||||
|
||||
extern "C" fn key_event(
|
||||
component: ComponentRefPin,
|
||||
key_event: &sixtyfps_corelib::input::KeyEvent,
|
||||
window: &sixtyfps_corelib::eventloop::ComponentWindow,
|
||||
) -> KeyEventResult {
|
||||
// This is fine since we can only be called with a component that with our vtable which is a ComponentDescription
|
||||
let component_type = unsafe { get_component_type(component) };
|
||||
let instance = unsafe { Pin::new_unchecked(&*component.as_ptr().cast::<Instance>()) };
|
||||
let extra_data = component_type.extra_data_offset.apply(&*instance);
|
||||
if let Some((item_index, rep_index)) = extra_data.focus_item.get().aborted_indexes() {
|
||||
let tree = &component_type.item_tree;
|
||||
match tree[item_index] {
|
||||
ItemTreeNode::Item { item, .. } => {
|
||||
item.apply_pin(instance).as_ref().key_event(key_event, window)
|
||||
}
|
||||
ItemTreeNode::DynamicTree { index } => {
|
||||
generativity::make_guard!(guard);
|
||||
let rep_in_comp = &component_type.repeater[index].unerase(guard);
|
||||
rep_in_comp.offset.apply_pin(instance).key_event(rep_index, key_event, window)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
KeyEventResult::EventIgnored
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn focus_event(
|
||||
component: ComponentRefPin,
|
||||
event: &FocusEvent,
|
||||
window: &sixtyfps_corelib::eventloop::ComponentWindow,
|
||||
) -> FocusEventResult {
|
||||
// This is fine since we can only be called with a component that with our vtable which is a ComponentDescription
|
||||
let component_type = unsafe { get_component_type(component) };
|
||||
let instance = unsafe { Pin::new_unchecked(&*component.as_ptr().cast::<Instance>()) };
|
||||
let extra_data = component_type.extra_data_offset.apply(&*instance);
|
||||
|
||||
match event {
|
||||
FocusEvent::FocusIn(_) => {
|
||||
generativity::make_guard!(guard);
|
||||
let instance_ref = unsafe { InstanceRef::from_pin_ref(component, guard) };
|
||||
let comp_rc = instance_ref.self_weak().get().unwrap().upgrade().unwrap();
|
||||
|
||||
let (event_result, visit_result) =
|
||||
sixtyfps_corelib::input::locate_and_activate_focus_item(
|
||||
&vtable::VRc::into_dyn(comp_rc),
|
||||
event,
|
||||
window,
|
||||
);
|
||||
if event_result == FocusEventResult::FocusItemFound {
|
||||
extra_data.focus_item.set(visit_result)
|
||||
}
|
||||
event_result
|
||||
}
|
||||
FocusEvent::FocusOut | FocusEvent::WindowReceivedFocus | FocusEvent::WindowLostFocus => {
|
||||
if let Some((item_index, rep_index)) = extra_data.focus_item.get().aborted_indexes() {
|
||||
let tree = &component_type.item_tree;
|
||||
match tree[item_index] {
|
||||
ItemTreeNode::Item { item, .. } => {
|
||||
item.apply_pin(instance).as_ref().focus_event(&event, window)
|
||||
}
|
||||
ItemTreeNode::DynamicTree { index } => {
|
||||
generativity::make_guard!(guard);
|
||||
let rep_in_comp = &component_type.repeater[index].unerase(guard);
|
||||
rep_in_comp
|
||||
.offset
|
||||
.apply_pin(instance)
|
||||
.focus_event(rep_index, &event, window);
|
||||
}
|
||||
};
|
||||
// Preserve the focus_item field unless we're clearing it as part of a focus out phase.
|
||||
if matches!(event, sixtyfps_corelib::input::FocusEvent::FocusOut) {
|
||||
extra_data.focus_item.set(VisitChildrenResult::CONTINUE);
|
||||
}
|
||||
FocusEventResult::FocusItemFound // We had a focus item and "found" it and notified it
|
||||
} else {
|
||||
FocusEventResult::FocusItemNotFound
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn layout_info(component: ComponentRefPin) -> LayoutInfo {
|
||||
generativity::make_guard!(guard);
|
||||
// This is fine since we can only be called with a component that with our vtable which is a ComponentDescription
|
||||
|
|
|
@ -402,12 +402,6 @@ pub fn eval_expression(e: &Expression, local_context: &mut EvalLocalContext) ->
|
|||
};
|
||||
if let Expression::ElementReference(focus_item) = &arguments[0] {
|
||||
generativity::make_guard!(guard);
|
||||
let component_ref: Pin<vtable::VRef<corelib::component::ComponentVTable>> = unsafe {
|
||||
Pin::new_unchecked(vtable::VRef::from_raw(
|
||||
core::ptr::NonNull::from(&component.component_type.ct).cast(),
|
||||
core::ptr::NonNull::from(&*component.as_ptr()),
|
||||
))
|
||||
};
|
||||
|
||||
let focus_item = focus_item.upgrade().unwrap();
|
||||
let enclosing_component =
|
||||
|
@ -415,10 +409,10 @@ pub fn eval_expression(e: &Expression, local_context: &mut EvalLocalContext) ->
|
|||
let component_type = enclosing_component.component_type;
|
||||
|
||||
let item_info = &component_type.items[focus_item.borrow().id.as_str()];
|
||||
let item =
|
||||
unsafe { item_info.item_from_component(enclosing_component.as_ptr()) };
|
||||
|
||||
window_ref(component).unwrap().set_focus_item(component_ref, item);
|
||||
let focus_item_comp = enclosing_component.self_weak().get().unwrap().upgrade().unwrap();
|
||||
|
||||
window_ref(component).unwrap().set_focus_item(&vtable::VRc::into_dyn(focus_item_comp), item_info.item_index());
|
||||
Value::Void
|
||||
} else {
|
||||
panic!("internal error: argument to SetFocusItem must be an element")
|
||||
|
|
|
@ -27,7 +27,7 @@ it needs to be kept in sync with different place.
|
|||
use const_field_offset::FieldOffsets;
|
||||
use core::pin::Pin;
|
||||
use cpp::cpp;
|
||||
use sixtyfps_corelib::component::{ComponentRefPin, ComponentVTable};
|
||||
use sixtyfps_corelib::component::ComponentVTable;
|
||||
use sixtyfps_corelib::eventloop::ComponentWindow;
|
||||
use sixtyfps_corelib::graphics::{HighLevelRenderingPrimitive, Rect, RenderingVariable, Resource};
|
||||
use sixtyfps_corelib::input::{
|
||||
|
@ -197,7 +197,8 @@ impl Item for NativeButton {
|
|||
self: Pin<&Self>,
|
||||
event: MouseEvent,
|
||||
_window: &ComponentWindow,
|
||||
_app_component: ComponentRefPin,
|
||||
_self_component: &vtable::VRc<ComponentVTable, vtable::Dyn>,
|
||||
_self_index: usize,
|
||||
) -> InputEventResult {
|
||||
let enabled = Self::FIELD_OFFSETS.enabled.apply_pin(self).get();
|
||||
if !enabled {
|
||||
|
@ -329,7 +330,8 @@ impl Item for NativeCheckBox {
|
|||
self: Pin<&Self>,
|
||||
event: MouseEvent,
|
||||
_window: &ComponentWindow,
|
||||
_app_component: ComponentRefPin,
|
||||
_self_component: &vtable::VRc<ComponentVTable, vtable::Dyn>,
|
||||
_self_index: usize,
|
||||
) -> InputEventResult {
|
||||
if matches!(event.what, MouseEventType::MouseReleased) {
|
||||
Self::FIELD_OFFSETS
|
||||
|
@ -490,7 +492,8 @@ impl Item for NativeSpinBox {
|
|||
self: Pin<&Self>,
|
||||
event: MouseEvent,
|
||||
_window: &ComponentWindow,
|
||||
_app_component: ComponentRefPin,
|
||||
_self_component: &vtable::VRc<ComponentVTable, vtable::Dyn>,
|
||||
_self_index: usize,
|
||||
) -> InputEventResult {
|
||||
let size: qttypes::QSize = get_size!(self);
|
||||
let enabled = Self::FIELD_OFFSETS.enabled.apply_pin(self).get();
|
||||
|
@ -697,7 +700,8 @@ impl Item for NativeSlider {
|
|||
self: Pin<&Self>,
|
||||
event: MouseEvent,
|
||||
_window: &ComponentWindow,
|
||||
_app_component: ComponentRefPin,
|
||||
_self_component: &vtable::VRc<ComponentVTable, vtable::Dyn>,
|
||||
_self_index: usize,
|
||||
) -> InputEventResult {
|
||||
let size: qttypes::QSize = get_size!(self);
|
||||
let enabled = Self::FIELD_OFFSETS.enabled.apply_pin(self).get();
|
||||
|
@ -955,7 +959,8 @@ impl Item for NativeGroupBox {
|
|||
self: Pin<&Self>,
|
||||
_: MouseEvent,
|
||||
_window: &ComponentWindow,
|
||||
_app_component: ComponentRefPin,
|
||||
_self_component: &vtable::VRc<ComponentVTable, vtable::Dyn>,
|
||||
_self_index: usize,
|
||||
) -> InputEventResult {
|
||||
InputEventResult::EventIgnored
|
||||
}
|
||||
|
@ -1107,7 +1112,8 @@ impl Item for NativeLineEdit {
|
|||
self: Pin<&Self>,
|
||||
_: MouseEvent,
|
||||
_window: &ComponentWindow,
|
||||
_app_component: ComponentRefPin,
|
||||
_self_component: &vtable::VRc<ComponentVTable, vtable::Dyn>,
|
||||
_self_index: usize,
|
||||
) -> InputEventResult {
|
||||
InputEventResult::EventIgnored
|
||||
}
|
||||
|
@ -1358,7 +1364,8 @@ impl Item for NativeScrollView {
|
|||
self: Pin<&Self>,
|
||||
event: MouseEvent,
|
||||
window: &ComponentWindow,
|
||||
_app_component: ComponentRefPin,
|
||||
_self_component: &vtable::VRc<ComponentVTable, vtable::Dyn>,
|
||||
_self_index: usize,
|
||||
) -> InputEventResult {
|
||||
let dpr = window.scale_factor();
|
||||
let size: qttypes::QSize = get_size!(self);
|
||||
|
@ -1623,7 +1630,8 @@ impl Item for NativeStandardListViewItem {
|
|||
self: Pin<&Self>,
|
||||
_event: MouseEvent,
|
||||
_window: &ComponentWindow,
|
||||
_app_component: ComponentRefPin,
|
||||
_self_component: &vtable::VRc<ComponentVTable, vtable::Dyn>,
|
||||
_self_index: usize,
|
||||
) -> InputEventResult {
|
||||
InputEventResult::EventIgnored
|
||||
}
|
||||
|
@ -1744,7 +1752,8 @@ impl Item for NativeComboBox {
|
|||
self: Pin<&Self>,
|
||||
event: MouseEvent,
|
||||
_window: &ComponentWindow,
|
||||
_app_component: ComponentRefPin,
|
||||
_self_component: &vtable::VRc<ComponentVTable, vtable::Dyn>,
|
||||
_self_index: usize,
|
||||
) -> InputEventResult {
|
||||
let enabled = Self::FIELD_OFFSETS.enabled.apply_pin(self).get();
|
||||
if !enabled {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue