use { crate::{ fixed::Fixed, ifs::wl_seat::tablet::{TabletTool, TabletToolChanges, ToolButtonState}, time::now_usec, tree::{FindTreeUsecase, FoundNode, Node}, utils::{clonecell::CloneCell, smallmap::SmallMap}, }, std::rc::Rc, }; pub struct ToolOwnerHolder { default: Rc, owner: CloneCell>, } struct DefaultToolOwner; struct GrabToolOwner { buttons: SmallMap, node: Rc, } impl Default for ToolOwnerHolder { fn default() -> Self { let default = Rc::new(DefaultToolOwner); Self { owner: CloneCell::new(default.clone()), default, } } } impl ToolOwnerHolder { pub fn destroy(&self, tool: &Rc) { let root = tool.tablet.seat.state.root.clone(); let prev = tool.node.set(root); prev.node_on_tablet_tool_leave(tool, now_usec()); prev.node_seat_state().remove_tablet_tool_focus(tool); } pub fn focus_root(&self, tool: &Rc) { self.owner.set(self.default.clone()); let root = tool.tablet.seat.state.root.clone(); tool.set_node(root, now_usec()); } pub fn button( &self, tool: &Rc, time_usec: u64, button: u32, state: ToolButtonState, ) { self.owner.get().button(tool, time_usec, button, state); } pub fn apply_changes( &self, tool: &Rc, time_usec: u64, changes: Option<&TabletToolChanges>, ) { self.owner.get().apply_changes(tool, time_usec, changes); } } trait ToolOwner { fn button(&self, tool: &Rc, time_usec: u64, button: u32, state: ToolButtonState); fn apply_changes( &self, tool: &Rc, time_usec: u64, changes: Option<&TabletToolChanges>, ); } impl TabletTool { fn set_node(self: &Rc, node: Rc, time_usec: u64) { let prev = self.node.set(node.clone()); if prev.node_id() != node.node_id() { prev.node_on_tablet_tool_leave(self, time_usec); prev.node_seat_state().remove_tablet_tool_focus(self); let (tool_x, tool_y) = self.cursor.position(); let (node_x, node_y) = node.node_absolute_position().position(); node.node_seat_state().add_tablet_tool_focus(self); node.node_on_tablet_tool_enter(self, time_usec, tool_x - node_x, tool_y - node_y); } } } impl ToolOwner for DefaultToolOwner { fn button(&self, tool: &Rc, time_usec: u64, button: u32, state: ToolButtonState) { if state == ToolButtonState::Released { return; } let owner = Rc::new(GrabToolOwner { buttons: Default::default(), node: tool.node.get(), }); tool.tool_owner.owner.set(owner.clone()); owner.button(tool, time_usec, button, state); } fn apply_changes( &self, tool: &Rc, time_usec: u64, changes: Option<&TabletToolChanges>, ) { let change = handle_position_change(tool); let node = change.node; if change.changed { tool.set_node(node.clone(), time_usec); } else { node.clone() .node_on_tablet_tool_apply_changes(tool, time_usec, changes, change.x, change.y); } if tool.down.get() { tool.tool_owner.owner.set(Rc::new(GrabToolOwner { buttons: Default::default(), node, })); } } } impl GrabToolOwner { fn maybe_revert(&self, tool: &Rc) { if !tool.down.get() && self.buttons.is_empty() { tool.tool_owner.owner.set(tool.tool_owner.default.clone()); tool.tablet.seat.tree_changed.trigger(); } } } impl ToolOwner for GrabToolOwner { fn button(&self, tool: &Rc, time_usec: u64, button: u32, state: ToolButtonState) { match state { ToolButtonState::Released => { if self.buttons.remove(&button).is_none() { return; } } ToolButtonState::Pressed => { if self.buttons.insert(button, ()).is_some() { return; } } } self.node .node_on_tablet_tool_button(tool, time_usec, button, state); self.maybe_revert(tool); } fn apply_changes( &self, tool: &Rc, time_usec: u64, changes: Option<&TabletToolChanges>, ) { let (x, y) = tool.cursor.position(); let node_pos = self.node.node_absolute_position(); self.node.clone().node_on_tablet_tool_apply_changes( tool, time_usec, changes, x - node_pos.x1(), y - node_pos.y1(), ); self.maybe_revert(tool); } } fn handle_position_change(tool: &Rc) -> UpdatedNode { let (x, y) = tool.cursor.position(); let x_int = x.round_down(); let y_int = y.round_down(); let tree = &mut *tool.tablet.tree.borrow_mut(); tree.push(FoundNode { node: tool.tablet.seat.state.root.clone(), x: x_int, y: y_int, }); tool.tablet .seat .state .root .node_find_tree_at(x_int, y_int, tree, FindTreeUsecase::None); let mut update = UpdatedNode { node: tool.node.get(), x, y, changed: false, }; if let Some(last) = tree.last() { if last.node.node_id() != update.node.node_id() { update.changed = true; update.node = last.node.clone(); } update.x = x.apply_fract(last.x); update.y = y.apply_fract(last.y); } tree.clear(); update } struct UpdatedNode { node: Rc, changed: bool, x: Fixed, y: Fixed, }