1
0
Fork 0
forked from wry/wry
wry/src/ifs/wl_seat/tablet/tool_owner.rs

215 lines
6 KiB
Rust

use {
crate::{
fixed::Fixed,
ifs::wl_seat::tablet::{TabletTool, TabletToolChanges, ToolButtonState},
tree::{FindTreeUsecase, FoundNode, Node},
utils::{clonecell::CloneCell, smallmap::SmallMap},
},
std::rc::Rc,
};
pub struct ToolOwnerHolder {
default: Rc<DefaultToolOwner>,
owner: CloneCell<Rc<dyn ToolOwner>>,
}
struct DefaultToolOwner;
struct GrabToolOwner {
buttons: SmallMap<u32, (), 4>,
node: Rc<dyn Node>,
}
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<TabletTool>) {
let root = tool.tablet.seat.state.root.clone();
let prev = tool.node.set(root);
prev.node_on_tablet_tool_leave(tool, tool.tablet.seat.state.now_usec());
prev.node_seat_state().remove_tablet_tool_focus(tool);
}
pub fn focus_root(&self, tool: &Rc<TabletTool>) {
self.owner.set(self.default.clone());
let state = &tool.tablet.seat.state;
let root = state.root.clone();
tool.set_node(root, state.now_usec());
}
pub fn button(
&self,
tool: &Rc<TabletTool>,
time_usec: u64,
button: u32,
state: ToolButtonState,
) {
self.owner.get().button(tool, time_usec, button, state);
}
pub fn apply_changes(
&self,
tool: &Rc<TabletTool>,
time_usec: u64,
changes: Option<&TabletToolChanges>,
) {
self.owner.get().apply_changes(tool, time_usec, changes);
}
}
trait ToolOwner {
fn button(&self, tool: &Rc<TabletTool>, time_usec: u64, button: u32, state: ToolButtonState);
fn apply_changes(
&self,
tool: &Rc<TabletTool>,
time_usec: u64,
changes: Option<&TabletToolChanges>,
);
}
impl TabletTool {
fn set_node(self: &Rc<Self>, node: Rc<dyn Node>, 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<TabletTool>, time_usec: u64, button: u32, state: ToolButtonState) {
if state == ToolButtonState::Released {
return;
}
let node = tool.node.get();
node.node_restack();
let owner = Rc::new(GrabToolOwner {
buttons: Default::default(),
node,
});
tool.tool_owner.owner.set(owner.clone());
owner.button(tool, time_usec, button, state);
}
fn apply_changes(
&self,
tool: &Rc<TabletTool>,
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<TabletTool>) {
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<TabletTool>, 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<TabletTool>,
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<TabletTool>) -> 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<dyn Node>,
changed: bool,
x: Fixed,
y: Fixed,
}