Merge remote-tracking branch 'upstream/master' into tui_focus

This commit is contained in:
Evan Almloff committed 2022-05-05 12:46:25 -05:00
commit 5c52396482
1 file changed
+47 -63
+47 -63
View File
@@ -31,22 +31,22 @@ use crate::{Dom, Node};
// pub fn mouse(&self) -> Option<MouseData> { // pub fn mouse(&self) -> Option<MouseData> {
// let data = (**self.0).borrow(); // let data = (**self.0).borrow();
// data.mouse.as_ref().map(|m| m.clone()) // mouse.as_ref().map(|m| m.clone())
// } // }
// pub fn wheel(&self) -> Option<WheelData> { // pub fn wheel(&self) -> Option<WheelData> {
// let data = (**self.0).borrow(); // let data = (**self.0).borrow();
// data.wheel.as_ref().map(|w| w.clone()) // wheel.as_ref().map(|w| w.clone())
// } // }
// pub fn screen(&self) -> Option<(u16, u16)> { // pub fn screen(&self) -> Option<(u16, u16)> {
// let data = (**self.0).borrow(); // let data = (**self.0).borrow();
// data.screen.as_ref().map(|m| m.clone()) // screen.as_ref().map(|m| m.clone())
// } // }
// pub fn last_key_pressed(&self) -> Option<KeyboardData> { // pub fn last_key_pressed(&self) -> Option<KeyboardData> {
// let data = (**self.0).borrow(); // let data = (**self.0).borrow();
// data.last_key_pressed // last_key_pressed
// .as_ref() // .as_ref()
// .map(|k| &k.0.clone()) // .map(|k| &k.0.clone())
// } // }
@@ -215,16 +215,6 @@ impl InnerInputState {
layout: &Stretch, layout: &Stretch,
dom: &mut Dom, dom: &mut Dom,
) { ) {
struct Data<'b> {
new_pos: (i32, i32),
old_pos: Option<(i32, i32)>,
clicked: bool,
released: bool,
wheel_delta: f64,
mouse_data: &'b MouseData,
wheel_data: &'b Option<WheelData>,
}
fn layout_contains_point(layout: &Layout, point: (i32, i32)) -> bool { fn layout_contains_point(layout: &Layout, point: (i32, i32)) -> bool {
layout.location.x as i32 <= point.0 layout.location.x as i32 <= point.0
&& layout.location.x as i32 + layout.size.width as i32 >= point.0 && layout.location.x as i32 + layout.size.width as i32 >= point.0
@@ -257,6 +247,13 @@ impl InnerInputState {
} }
} }
fn prepare_mouse_data(mouse_data: &MouseData, layout: &Layout) -> MouseData {
let mut data = mouse_data.clone();
data.offset_x = data.client_x - layout.location.x as i32;
data.offset_y = data.client_y - layout.location.y as i32;
data
}
if let Some(mouse) = &self.mouse { if let Some(mouse) = &self.mouse {
let new_pos = (mouse.0.screen_x, mouse.0.screen_y); let new_pos = (mouse.0.screen_x, mouse.0.screen_y);
let old_pos = previous_mouse let old_pos = previous_mouse
@@ -269,31 +266,21 @@ impl InnerInputState {
let wheel_delta = self.wheel.as_ref().map_or(0.0, |w| w.delta_y); let wheel_delta = self.wheel.as_ref().map_or(0.0, |w| w.delta_y);
let mouse_data = &mouse.0; let mouse_data = &mouse.0;
let wheel_data = &self.wheel; let wheel_data = &self.wheel;
let data = Data {
new_pos,
old_pos,
clicked,
released,
wheel_delta,
mouse_data,
wheel_data,
};
{ {
// mousemove // mousemove
let mut will_bubble = FxHashSet::default(); let mut will_bubble = FxHashSet::default();
for node in dom.get_listening_sorted("mousemove") { for node in dom.get_listening_sorted("mousemove") {
let node_layout = layout.layout(node.state.layout.node.unwrap()).unwrap(); let node_layout = layout.layout(node.state.layout.node.unwrap()).unwrap();
let previously_contained = data let previously_contained = old_pos
.old_pos
.filter(|pos| layout_contains_point(node_layout, *pos)) .filter(|pos| layout_contains_point(node_layout, *pos))
.is_some(); .is_some();
let currently_contains = layout_contains_point(node_layout, data.new_pos); let currently_contains = layout_contains_point(node_layout, new_pos);
if currently_contains && previously_contained { if currently_contains && previously_contained {
try_create_event( try_create_event(
"mousemove", "mousemove",
Arc::new(data.mouse_data.clone()), Arc::new(prepare_mouse_data(mouse_data, node_layout)),
&mut will_bubble, &mut will_bubble,
resolved_events, resolved_events,
node, node,
@@ -308,16 +295,15 @@ impl InnerInputState {
let mut will_bubble = FxHashSet::default(); let mut will_bubble = FxHashSet::default();
for node in dom.get_listening_sorted("mouseenter") { for node in dom.get_listening_sorted("mouseenter") {
let node_layout = layout.layout(node.state.layout.node.unwrap()).unwrap(); let node_layout = layout.layout(node.state.layout.node.unwrap()).unwrap();
let previously_contained = data let previously_contained = old_pos
.old_pos
.filter(|pos| layout_contains_point(node_layout, *pos)) .filter(|pos| layout_contains_point(node_layout, *pos))
.is_some(); .is_some();
let currently_contains = layout_contains_point(node_layout, data.new_pos); let currently_contains = layout_contains_point(node_layout, new_pos);
if currently_contains && !previously_contained { if currently_contains && !previously_contained {
try_create_event( try_create_event(
"mouseenter", "mouseenter",
Arc::new(data.mouse_data.clone()), Arc::new(mouse_data.clone()),
&mut will_bubble, &mut will_bubble,
resolved_events, resolved_events,
node, node,
@@ -332,16 +318,15 @@ impl InnerInputState {
let mut will_bubble = FxHashSet::default(); let mut will_bubble = FxHashSet::default();
for node in dom.get_listening_sorted("mouseover") { for node in dom.get_listening_sorted("mouseover") {
let node_layout = layout.layout(node.state.layout.node.unwrap()).unwrap(); let node_layout = layout.layout(node.state.layout.node.unwrap()).unwrap();
let previously_contained = data let previously_contained = old_pos
.old_pos
.filter(|pos| layout_contains_point(node_layout, *pos)) .filter(|pos| layout_contains_point(node_layout, *pos))
.is_some(); .is_some();
let currently_contains = layout_contains_point(node_layout, data.new_pos); let currently_contains = layout_contains_point(node_layout, new_pos);
if currently_contains && !previously_contained { if currently_contains && !previously_contained {
try_create_event( try_create_event(
"mouseover", "mouseover",
Arc::new(data.mouse_data.clone()), Arc::new(prepare_mouse_data(mouse_data, node_layout)),
&mut will_bubble, &mut will_bubble,
resolved_events, resolved_events,
node, node,
@@ -352,16 +337,16 @@ impl InnerInputState {
} }
// mousedown // mousedown
if data.clicked { if clicked {
let mut will_bubble = FxHashSet::default(); let mut will_bubble = FxHashSet::default();
for node in dom.get_listening_sorted("mousedown") { for node in dom.get_listening_sorted("mousedown") {
let node_layout = layout.layout(node.state.layout.node.unwrap()).unwrap(); let node_layout = layout.layout(node.state.layout.node.unwrap()).unwrap();
let currently_contains = layout_contains_point(node_layout, data.new_pos); let currently_contains = layout_contains_point(node_layout, new_pos);
if currently_contains { if currently_contains {
try_create_event( try_create_event(
"mousedown", "mousedown",
Arc::new(data.mouse_data.clone()), Arc::new(prepare_mouse_data(mouse_data, node_layout)),
&mut will_bubble, &mut will_bubble,
resolved_events, resolved_events,
node, node,
@@ -372,16 +357,16 @@ impl InnerInputState {
} }
// mouseup // mouseup
if data.released { if released {
let mut will_bubble = FxHashSet::default(); let mut will_bubble = FxHashSet::default();
for node in dom.get_listening_sorted("mouseup") { for node in dom.get_listening_sorted("mouseup") {
let node_layout = layout.layout(node.state.layout.node.unwrap()).unwrap(); let node_layout = layout.layout(node.state.layout.node.unwrap()).unwrap();
let currently_contains = layout_contains_point(node_layout, data.new_pos); let currently_contains = layout_contains_point(node_layout, new_pos);
if currently_contains { if currently_contains {
try_create_event( try_create_event(
"mouseup", "mouseup",
Arc::new(data.mouse_data.clone()), Arc::new(prepare_mouse_data(mouse_data, node_layout)),
&mut will_bubble, &mut will_bubble,
resolved_events, resolved_events,
node, node,
@@ -392,16 +377,16 @@ impl InnerInputState {
} }
// click // click
if data.released && data.mouse_data.button == 0 { if released && mouse_data.button == 0 {
let mut will_bubble = FxHashSet::default(); let mut will_bubble = FxHashSet::default();
for node in dom.get_listening_sorted("click") { for node in dom.get_listening_sorted("click") {
let node_layout = layout.layout(node.state.layout.node.unwrap()).unwrap(); let node_layout = layout.layout(node.state.layout.node.unwrap()).unwrap();
let currently_contains = layout_contains_point(node_layout, data.new_pos); let currently_contains = layout_contains_point(node_layout, new_pos);
if currently_contains { if currently_contains {
try_create_event( try_create_event(
"click", "click",
Arc::new(data.mouse_data.clone()), Arc::new(prepare_mouse_data(mouse_data, node_layout)),
&mut will_bubble, &mut will_bubble,
resolved_events, resolved_events,
node, node,
@@ -412,16 +397,16 @@ impl InnerInputState {
} }
// contextmenu // contextmenu
if data.released && data.mouse_data.button == 2 { if released && mouse_data.button == 2 {
let mut will_bubble = FxHashSet::default(); let mut will_bubble = FxHashSet::default();
for node in dom.get_listening_sorted("contextmenu") { for node in dom.get_listening_sorted("contextmenu") {
let node_layout = layout.layout(node.state.layout.node.unwrap()).unwrap(); let node_layout = layout.layout(node.state.layout.node.unwrap()).unwrap();
let currently_contains = layout_contains_point(node_layout, data.new_pos); let currently_contains = layout_contains_point(node_layout, new_pos);
if currently_contains { if currently_contains {
try_create_event( try_create_event(
"contextmenu", "contextmenu",
Arc::new(data.mouse_data.clone()), Arc::new(prepare_mouse_data(mouse_data, node_layout)),
&mut will_bubble, &mut will_bubble,
resolved_events, resolved_events,
node, node,
@@ -432,12 +417,12 @@ impl InnerInputState {
} }
// wheel // wheel
if let Some(w) = data.wheel_data { if let Some(w) = wheel_data {
if data.wheel_delta != 0.0 { if wheel_delta != 0.0 {
let mut will_bubble = FxHashSet::default(); let mut will_bubble = FxHashSet::default();
for node in dom.get_listening_sorted("wheel") { for node in dom.get_listening_sorted("wheel") {
let node_layout = layout.layout(node.state.layout.node.unwrap()).unwrap(); let node_layout = layout.layout(node.state.layout.node.unwrap()).unwrap();
let currently_contains = layout_contains_point(node_layout, data.new_pos); let currently_contains = layout_contains_point(node_layout, new_pos);
if currently_contains { if currently_contains {
try_create_event( try_create_event(
@@ -458,16 +443,15 @@ impl InnerInputState {
let mut will_bubble = FxHashSet::default(); let mut will_bubble = FxHashSet::default();
for node in dom.get_listening_sorted("mouseleave") { for node in dom.get_listening_sorted("mouseleave") {
let node_layout = layout.layout(node.state.layout.node.unwrap()).unwrap(); let node_layout = layout.layout(node.state.layout.node.unwrap()).unwrap();
let previously_contained = data let previously_contained = old_pos
.old_pos
.filter(|pos| layout_contains_point(node_layout, *pos)) .filter(|pos| layout_contains_point(node_layout, *pos))
.is_some(); .is_some();
let currently_contains = layout_contains_point(node_layout, data.new_pos); let currently_contains = layout_contains_point(node_layout, new_pos);
if !currently_contains && previously_contained { if !currently_contains && previously_contained {
try_create_event( try_create_event(
"mouseleave", "mouseleave",
Arc::new(data.mouse_data.clone()), Arc::new(prepare_mouse_data(mouse_data, node_layout)),
&mut will_bubble, &mut will_bubble,
resolved_events, resolved_events,
node, node,
@@ -482,16 +466,15 @@ impl InnerInputState {
let mut will_bubble = FxHashSet::default(); let mut will_bubble = FxHashSet::default();
for node in dom.get_listening_sorted("mouseout") { for node in dom.get_listening_sorted("mouseout") {
let node_layout = layout.layout(node.state.layout.node.unwrap()).unwrap(); let node_layout = layout.layout(node.state.layout.node.unwrap()).unwrap();
let previously_contained = data let previously_contained = old_pos
.old_pos
.filter(|pos| layout_contains_point(node_layout, *pos)) .filter(|pos| layout_contains_point(node_layout, *pos))
.is_some(); .is_some();
let currently_contains = layout_contains_point(node_layout, data.new_pos); let currently_contains = layout_contains_point(node_layout, new_pos);
if !currently_contains && previously_contained { if !currently_contains && previously_contained {
try_create_event( try_create_event(
"mouseout", "mouseout",
Arc::new(data.mouse_data.clone()), Arc::new(prepare_mouse_data(mouse_data, node_layout)),
&mut will_bubble, &mut will_bubble,
resolved_events, resolved_events,
node, node,
@@ -502,11 +485,11 @@ impl InnerInputState {
} }
// update focus // update focus
if data.released { if released {
let mut focus_id = None; let mut focus_id = None;
dom.traverse_depth_first(|node| { dom.traverse_depth_first(|node| {
let node_layout = layout.layout(node.state.layout.node.unwrap()).unwrap(); let node_layout = layout.layout(node.state.layout.node.unwrap()).unwrap();
let currently_contains = layout_contains_point(node_layout, data.new_pos); let currently_contains = layout_contains_point(node_layout, new_pos);
if currently_contains && node.state.focus.level.focusable() { if currently_contains && node.state.focus.level.focusable() {
focus_id = Some(node.id); focus_id = Some(node.id);
@@ -656,7 +639,7 @@ fn get_event(evt: TermEvent) -> Option<(&'static str, EventData)> {
}; };
// from https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent // from https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent
// The `offset`, `page` and `screen` coordinates are inconsistent with the MDN definition, as they are relative to the viewport (client), not the target element/page/screen, respectively. // The `page` and `screen` coordinates are inconsistent with the MDN definition, as they are relative to the viewport (client), not the target element/page/screen, respectively.
// todo? // todo?
// But then, MDN defines them in terms of pixels, yet crossterm provides only row/column, and it might not be possible to get pixels. So we can't get 100% consistency anyway. // But then, MDN defines them in terms of pixels, yet crossterm provides only row/column, and it might not be possible to get pixels. So we can't get 100% consistency anyway.
EventData::Mouse(MouseData { EventData::Mouse(MouseData {
@@ -667,8 +650,9 @@ fn get_event(evt: TermEvent) -> Option<(&'static str, EventData)> {
client_y: y, client_y: y,
ctrl_key: ctrl, ctrl_key: ctrl,
meta_key: meta, meta_key: meta,
offset_x: x, // offset x/y are set when the origin of the event is assigned to an element
offset_y: y, offset_x: 0,
offset_y: 0,
page_x: x, page_x: x,
page_y: y, page_y: y,
screen_x: x, screen_x: x,