change focus when an element is clicked

This commit is contained in:
Evan Almloff committed 2022-05-03 17:19:16 -05:00
1 parent 23376fef8e
commit 9ed722ae45
4 files changed
+83 -38

No files matched your search

+5 -1
View File
@@ -64,7 +64,9 @@ impl PersistantElementIter {
} }
/// remove stale element refreneces /// remove stale element refreneces
pub fn prune<S: State>(&mut self, mutations: &Mutations, rdom: &RealDom<S>) { /// returns true if the focused element is removed
pub fn prune<S: State>(&mut self, mutations: &Mutations, rdom: &RealDom<S>) -> bool {
let mut changed = false;
let ids_removed: Vec<_> = mutations let ids_removed: Vec<_> = mutations
.edits .edits
.iter() .iter()
@@ -82,6 +84,7 @@ impl PersistantElementIter {
.position(|(el_id, _)| ids_removed.iter().any(|id| el_id.as_u64() == *id)) .position(|(el_id, _)| ids_removed.iter().any(|id| el_id.as_u64() == *id))
{ {
self.stack.truncate(r); self.stack.truncate(r);
changed = true;
} }
// if a child is removed or inserted before or at the current element, update the child index // if a child is removed or inserted before or at the current element, update the child index
for (el_id, child_idx) in self.stack.iter_mut() { for (el_id, child_idx) in self.stack.iter_mut() {
@@ -122,6 +125,7 @@ impl PersistantElementIter {
} }
} }
} }
changed
} }
/// get the next element /// get the next element
+24 -1
View File
@@ -109,10 +109,11 @@ pub(crate) struct FocusState {
pub(crate) focus_iter: PersistantElementIter, pub(crate) focus_iter: PersistantElementIter,
pub(crate) last_focused_id: Option<ElementId>, pub(crate) last_focused_id: Option<ElementId>,
pub(crate) focus_level: FocusLevel, pub(crate) focus_level: FocusLevel,
pub(crate) dirty: bool,
} }
impl FocusState { impl FocusState {
// returns true if the focus has changed /// Returns true if the focus has changed.
pub fn progress(&mut self, rdom: &mut Dom, forward: bool) -> bool { pub fn progress(&mut self, rdom: &mut Dom, forward: bool) -> bool {
if let Some(last) = self.last_focused_id { if let Some(last) = self.last_focused_id {
if !rdom[last].state.focus.pass_focus { if !rdom[last].state.focus.pass_focus {
@@ -227,6 +228,7 @@ impl FocusState {
self.focus_iter.prev(&rdom).id() self.focus_iter.prev(&rdom).id()
} != id } != id
{} {}
self.dirty = true;
return true; return true;
} }
} }
@@ -253,6 +255,9 @@ impl FocusState {
} }
} }
} }
if self.focus_iter.prune(mutations, rdom) {
self.dirty = true;
}
for m in &mutations.edits { for m in &mutations.edits {
match m { match m {
dioxus_core::DomEdit::ReplaceWith { root, .. } => remove_children( dioxus_core::DomEdit::ReplaceWith { root, .. } => remove_children(
@@ -269,4 +274,22 @@ impl FocusState {
} }
} }
} }
pub(crate) fn set_focus(&mut self, rdom: &mut Dom, id: ElementId) {
if let Some(old) = self.last_focused_id.replace(id) {
rdom[old].state.focused = false;
}
let state = &mut rdom[id].state;
state.focused = true;
self.focus_level = state.focus.level;
// reset the position to the currently focused element
while self.focus_iter.next(&rdom).id() != id {}
self.dirty = true;
}
pub(crate) fn clean(&mut self) -> bool {
let old = self.dirty;
self.dirty = false;
old
}
} }
+50 -34
View File
@@ -7,7 +7,7 @@ use fxhash::{FxHashMap, FxHashSet};
use dioxus_html::{on::*, KeyCode}; use dioxus_html::{on::*, KeyCode};
use std::{ use std::{
any::Any, any::Any,
cell::RefCell, cell::{RefCell, RefMut},
rc::Rc, rc::Rc,
sync::Arc, sync::Arc,
time::{Duration, Instant}, time::{Duration, Instant},
@@ -79,7 +79,7 @@ pub struct InnerInputState {
wheel: Option<WheelData>, wheel: Option<WheelData>,
last_key_pressed: Option<(KeyboardData, Instant)>, last_key_pressed: Option<(KeyboardData, Instant)>,
screen: Option<(u16, u16)>, screen: Option<(u16, u16)>,
focus_state: FocusState, pub(crate) focus_state: FocusState,
// subscribers: Vec<Rc<dyn Fn() + 'static>>, // subscribers: Vec<Rc<dyn Fn() + 'static>>,
} }
@@ -170,19 +170,14 @@ impl InnerInputState {
resolved_events: &mut Vec<UserEvent>, resolved_events: &mut Vec<UserEvent>,
layout: &Stretch, layout: &Stretch,
dom: &mut Dom, dom: &mut Dom,
) -> bool { ) {
let previous_mouse = self.mouse.as_ref().map(|m| (m.0.clone(), m.1.clone())); let previous_mouse = self.mouse.as_ref().map(|m| (m.0.clone(), m.1.clone()));
self.wheel = None; self.wheel = None;
let mut force_redraw = false;
evts.retain(|e| match &e.1 { evts.retain(|e| match &e.1 {
EventData::Keyboard(k) => match k.key_code { EventData::Keyboard(k) => match k.key_code {
KeyCode::Tab => { KeyCode::Tab => !self.focus_state.progress(dom, !k.shift_key),
let focus_event = self.focus_state.progress(dom, !k.shift_key);
force_redraw |= focus_event;
!focus_event
}
_ => true, _ => true,
}, },
_ => true, _ => true,
@@ -197,11 +192,10 @@ impl InnerInputState {
// for s in &self.subscribers { // for s in &self.subscribers {
// s(); // s();
// } // }
force_redraw
} }
fn resolve_mouse_events( fn resolve_mouse_events(
&self, &mut self,
previous_mouse: Option<(MouseData, Vec<u16>)>, previous_mouse: Option<(MouseData, Vec<u16>)>,
resolved_events: &mut Vec<UserEvent>, resolved_events: &mut Vec<UserEvent>,
layout: &Stretch, layout: &Stretch,
@@ -343,14 +337,14 @@ impl InnerInputState {
} }
} }
{ // mousedown
// mousedown if data.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, data.new_pos);
if currently_contains && data.clicked { if currently_contains {
try_create_event( try_create_event(
"mousedown", "mousedown",
Arc::new(data.mouse_data.clone()), Arc::new(data.mouse_data.clone()),
@@ -363,14 +357,14 @@ impl InnerInputState {
} }
} }
{ // mouseup
// mouseup if data.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, data.new_pos);
if currently_contains && data.released { if currently_contains {
try_create_event( try_create_event(
"mouseup", "mouseup",
Arc::new(data.mouse_data.clone()), Arc::new(data.mouse_data.clone()),
@@ -383,14 +377,14 @@ impl InnerInputState {
} }
} }
{ // click
// click if data.released && data.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, data.new_pos);
if currently_contains && data.released && data.mouse_data.button == 0 { if currently_contains {
try_create_event( try_create_event(
"click", "click",
Arc::new(data.mouse_data.clone()), Arc::new(data.mouse_data.clone()),
@@ -403,14 +397,14 @@ impl InnerInputState {
} }
} }
{ // contextmenu
// contextmenu if data.released && data.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, data.new_pos);
if currently_contains && data.released && data.mouse_data.button == 2 { if currently_contains {
try_create_event( try_create_event(
"contextmenu", "contextmenu",
Arc::new(data.mouse_data.clone()), Arc::new(data.mouse_data.clone()),
@@ -423,15 +417,15 @@ impl InnerInputState {
} }
} }
{ // wheel
// wheel if let Some(w) = data.wheel_data {
let mut will_bubble = FxHashSet::default(); if data.wheel_delta != 0.0 {
for node in dom.get_listening_sorted("wheel") { let mut will_bubble = FxHashSet::default();
let node_layout = layout.layout(node.state.layout.node.unwrap()).unwrap(); for node in dom.get_listening_sorted("wheel") {
let currently_contains = layout_contains_point(node_layout, data.new_pos); let node_layout = layout.layout(node.state.layout.node.unwrap()).unwrap();
let currently_contains = layout_contains_point(node_layout, data.new_pos);
if let Some(w) = data.wheel_data { if currently_contains {
if currently_contains && data.wheel_delta != 0.0 {
try_create_event( try_create_event(
"wheel", "wheel",
Arc::new(w.clone()), Arc::new(w.clone()),
@@ -492,6 +486,24 @@ impl InnerInputState {
} }
} }
} }
// update focus
if data.released {
let mut focus_id = None;
dom.traverse_depth_first(|node| {
let node_layout = layout.layout(node.state.layout.node.unwrap()).unwrap();
let currently_contains = layout_contains_point(node_layout, data.new_pos);
if currently_contains {
if node.state.focus.level.focusable() {
focus_id = Some(node.id);
}
}
});
if let Some(id) = focus_id {
self.focus_state.set_focus(dom, id);
}
}
} }
} }
@@ -541,10 +553,10 @@ impl RinkInputHandler {
} }
// returns a list of events and if a event will force a rerender // returns a list of events and if a event will force a rerender
pub(crate) fn get_events(&self, layout: &Stretch, dom: &mut Dom) -> (Vec<UserEvent>, bool) { pub(crate) fn get_events(&self, layout: &Stretch, dom: &mut Dom) -> Vec<UserEvent> {
let mut resolved_events = Vec::new(); let mut resolved_events = Vec::new();
let rerender = (*self.state).borrow_mut().update( (*self.state).borrow_mut().update(
&mut (*self.queued_events).borrow_mut(), &mut (*self.queued_events).borrow_mut(),
&mut resolved_events, &mut resolved_events,
layout, layout,
@@ -598,7 +610,11 @@ impl RinkInputHandler {
} }
} }
(resolved_events, rerender) resolved_events
}
pub(crate) fn state(&self) -> RefMut<InnerInputState> {
self.state.borrow_mut()
} }
} }
+4 -2
View File
@@ -223,8 +223,10 @@ fn render_vdom(
} }
{ {
let (evts, rerender) = handler.get_events(&stretch.borrow(), &mut rdom); let evts = handler.get_events(&stretch.borrow(), &mut rdom);
updated |= rerender; {
updated |= handler.state().focus_state.clean();
}
for e in evts { for e in evts {
vdom.handle_message(SchedulerMsg::Event(e)); vdom.handle_message(SchedulerMsg::Event(e));
} }