Prepare for key event delivery to a specific focus item

Begin by routing key events through the component. In the future that
will direct the event to the focus item.
This commit is contained in:
Simon Hausmann 2020-09-24 16:32:06 +02:00
parent 2b76e9277a
commit aa5babffe1
8 changed files with 82 additions and 15 deletions

View file

@ -134,6 +134,8 @@ constexpr inline ItemTreeNode make_dyn_node(std::uintptr_t offset)
}
using cbindgen_private::InputEventResult;
using cbindgen_private::KeyEvent;
using cbindgen_private::KeyEventResult;
using cbindgen_private::MouseEvent;
using cbindgen_private::sixtyfps_visit_item_tree;
namespace private_api {
@ -174,6 +176,14 @@ inline InputEventResult process_input_event(ComponentRef component, int64_t &mou
component, mouse_event, window, *app_component, &mouse_grabber);
}
}
template<typename GetDynamic>
inline KeyEventResult process_key_event(ComponentRef component, const KeyEvent *key_event,
Slice<ItemTreeNode> tree, GetDynamic get_dynamic,
const ComponentWindow *window)
{
return cbindgen_private::sixtyfps_process_key_event(component, key_event, window);
}
}
// layouts:

View file

@ -133,9 +133,9 @@ pub mod re_exports {
PathArcTo, PathData, PathElement, PathEvent, PathLineTo, Point, Rect, Size,
};
pub use sixtyfps_corelib::input::{
process_ungrabbed_mouse_event, InputEventResult, KeyCode, KeyEvent, KeyEventResult,
KeyboardModifiers, MouseEvent, ALT_MODIFIER, CONTROL_MODIFIER, COPY_PASTE_MODIFIER,
LOGO_MODIFIER, NO_MODIFIER, SHIFT_MODIFIER,
process_key_event, process_ungrabbed_mouse_event, 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,

View file

@ -858,6 +858,24 @@ fn generate_component(
}),
));
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![
format!(" auto self = reinterpret_cast<{}*>(component.instance);", component_id),
"return sixtyfps::private_api::process_key_event(component, key_event, item_tree(), [self](int dyn_index, [[maybe_unused]] int rep_index) {".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::Public, // FIXME: we call this function from tests
Declaration::Function(Function {
@ -885,7 +903,9 @@ fn generate_component(
declarations.push(Declaration::Var(Var {
ty: "const sixtyfps::private_api::ComponentVTable".to_owned(),
name: format!("{}::component_type", component_id),
init: Some("{ visit_children, nullptr, compute_layout, input_event }".to_owned()),
init: Some(
"{ visit_children, nullptr, compute_layout, input_event, key_event }".to_owned(),
),
}));
declarations.append(&mut file.declarations);

View file

@ -577,6 +577,12 @@ fn generate_component(
status
}
fn key_event(self: ::core::pin::Pin<&Self>, key_event : &sixtyfps::re_exports::KeyEvent, window: &sixtyfps::re_exports::ComponentWindow)
-> sixtyfps::re_exports::KeyEventResult{
use sixtyfps::re_exports::*;
process_key_event(VRef::new_pin(self), key_event, window)
}
#layouts
}

View file

@ -12,7 +12,7 @@ LICENSE END */
//! This module contains the basic datastructures that are exposed to the C API
use crate::eventloop::ComponentWindow;
use crate::input::{InputEventResult, MouseEvent};
use crate::input::{InputEventResult, KeyEvent, KeyEventResult, MouseEvent};
use crate::item_tree::{ItemVisitorVTable, TraversalOrder, VisitChildrenResult};
use crate::layout::LayoutInfo;
use vtable::*;
@ -44,6 +44,13 @@ pub struct ComponentVTable {
&ComponentWindow,
&core::pin::Pin<VRef<ComponentVTable>>,
) -> InputEventResult,
/// key event
pub key_event: extern "C" fn(
core::pin::Pin<VRef<ComponentVTable>>,
&KeyEvent,
&ComponentWindow,
) -> KeyEventResult,
}
/// Alias for `vtable::VRef<ComponentVTable>` which represent a pointer to a `dyn Component` with

View file

@ -620,11 +620,7 @@ impl<Backend: GraphicsBackend> crate::eventloop::GenericWindow for GraphicsWindo
event: &KeyEvent,
component: core::pin::Pin<crate::component::ComponentRef>,
) {
crate::input::process_key_event(
component,
event,
&crate::eventloop::ComponentWindow::new(self.clone()),
)
component.as_ref().key_event(event, &crate::eventloop::ComponentWindow::new(self.clone()));
}
fn with_platform_window(&self, callback: &dyn Fn(&winit::window::Window)) {

View file

@ -522,16 +522,21 @@ pub fn process_key_event(
component: ComponentRefPin,
event: &KeyEvent,
window: &crate::eventloop::ComponentWindow,
) {
) -> KeyEventResult {
let mut result = KeyEventResult::EventIgnored;
crate::item_tree::visit_items(
component,
crate::item_tree::TraversalOrder::BackToFront,
|_, item, _| match item.as_ref().key_event(event, window) {
|_, item, _| {
result = item.as_ref().key_event(event, window);
match result {
KeyEventResult::EventAccepted => ItemVisitorResult::Abort,
KeyEventResult::EventIgnored => ItemVisitorResult::Continue(()),
}
},
(),
);
result
}
pub(crate) mod ffi {
@ -560,4 +565,13 @@ 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_process_key_event(
component: core::pin::Pin<crate::component::ComponentRef>,
event: &KeyEvent,
window: &crate::eventloop::ComponentWindow,
) -> KeyEventResult {
process_key_event(component, event, window)
}
}

View file

@ -574,7 +574,13 @@ fn generate_component<'id>(
todo!()
}
let t = ComponentVTable { visit_children_item, layout_info, compute_layout, input_event };
let t = ComponentVTable {
visit_children_item,
layout_info,
compute_layout,
input_event,
key_event,
};
let t = ComponentDescription {
ct: t,
dynamic_type: builder.build(),
@ -1129,6 +1135,14 @@ extern "C" fn input_event(
status
}
extern "C" fn key_event(
component: ComponentRefPin,
key_event: &sixtyfps_corelib::input::KeyEvent,
window: &sixtyfps_corelib::eventloop::ComponentWindow,
) -> sixtyfps_corelib::input::KeyEventResult {
sixtyfps_corelib::input::process_key_event(component, key_event, window)
}
extern "C" fn compute_layout(component: ComponentRefPin) {
generativity::make_guard!(guard);
// This is fine since we can only be called with a component that with our vtable which is a ComponentDescription