1
0
Fork 0
forked from wry/wry
wry/src/ifs/wl_seat/tablet/tool.rs
2024-05-03 11:16:07 +02:00

274 lines
9.2 KiB
Rust

use {
crate::{
cursor::KnownCursor,
fixed::Fixed,
ifs::{
wl_seat::{
tablet::{
normalizei, normalizeu, zwp_tablet_tool_v2::ZwpTabletToolV2,
zwp_tablet_v2::ZwpTabletV2, TabletTool, TabletToolChanges, TabletToolId,
TabletToolInit, TabletToolOpt, TabletToolType, ToolButtonState,
},
WlSeatGlobal,
},
wl_surface::WlSurface,
},
rect::Rect,
time::usec_to_msec,
utils::clonecell::CloneCell,
},
std::{cell::Cell, rc::Rc},
};
impl WlSeatGlobal {
pub fn tablet_handle_remove_tool(self: &Rc<Self>, time_usec: u64, id: TabletToolId) {
let Some(tool) = self.tablet.tools.remove(&id) else {
return;
};
self.state.for_each_seat_tester(|t| {
t.send_tablet_tool_proximity_out(self.id, tool.tablet.dev, tool.id, time_usec)
});
tool.opt.tool.take();
tool.cursor.detach();
tool.tool_owner.destroy(&tool);
for (_, binding) in tool.bindings.lock().drain() {
binding.send_removed();
}
tool.tablet.tools.remove(&id);
}
pub fn tablet_handle_new_tool(self: &Rc<Self>, time_usec: u64, init: &TabletToolInit) {
let Some(tablet) = self.tablet.tablets.get(&init.tablet_id) else {
return;
};
let tool = Rc::new(TabletTool {
id: init.id,
opt: Default::default(),
tablet,
type_: init.type_,
hardware_serial: init.hardware_serial,
hardware_id_wacom: init.hardware_id_wacom,
capabilities: init.capabilities.clone(),
bindings: Default::default(),
node: CloneCell::new(self.state.root.clone()),
tool_owner: Default::default(),
cursor: self.cursor_user_group.create_user(),
down: Cell::new(false),
pressure: Cell::new(0.0),
distance: Cell::new(0.0),
tilt_x: Cell::new(0.0),
tilt_y: Cell::new(0.0),
rotation: Cell::new(0.0),
slider: Cell::new(0.0),
});
tool.opt.tool.set(Some(tool.clone()));
tool.cursor.set_known(KnownCursor::Default);
self.tablet.tools.set(init.id, tool.clone());
self.state.for_each_seat_tester(|t| {
t.send_tablet_tool_proximity_in(self.id, tool.tablet.dev, tool.id, time_usec)
});
self.tablet_for_each_seat_obj(|s| s.announce_tool(&tool));
}
pub fn tablet_event_tool_button(
self: &Rc<Self>,
id: TabletToolId,
time_usec: u64,
button: u32,
state: ToolButtonState,
) {
let Some(tool) = self.tablet.tools.get(&id) else {
return;
};
self.state.for_each_seat_tester(|t| {
t.send_tablet_tool_button(self.id, tool.tablet.dev, &tool, time_usec, button, state);
});
tool.cursor.activate();
tool.tool_owner.button(&tool, time_usec, button, state);
}
pub fn tablet_event_tool_changes(
self: &Rc<Self>,
id: TabletToolId,
time_usec: u64,
rect: Rect,
changes: &TabletToolChanges,
) {
let Some(tool) = self.tablet.tools.get(&id) else {
return;
};
self.state.for_each_seat_tester(|t| {
t.send_tablet_tool_changes(self.id, tool.tablet.dev, &tool, time_usec, changes);
});
if let Some(val) = changes.down {
tool.down.set(val);
}
if let Some(val) = changes.pressure {
tool.pressure.set(val);
}
if let Some(val) = changes.distance {
tool.distance.set(val);
}
if let Some(val) = changes.tilt {
tool.tilt_x.set(val.x);
tool.tilt_y.set(val.y);
}
if let Some(val) = changes.rotation {
tool.rotation.set(val);
}
if let Some(val) = changes.slider {
tool.slider.set(val);
}
if let Some(delta) = changes.pos {
let (x, y) = match tool.type_ {
TabletToolType::Mouse | TabletToolType::Lens => {
let (mut x, mut y) = tool.cursor.position();
x += Fixed::from_f64(delta.x.dx);
y += Fixed::from_f64(delta.y.dx);
(x, y)
}
TabletToolType::Pen
| TabletToolType::Eraser
| TabletToolType::Brush
| TabletToolType::Pencil
| TabletToolType::Airbrush
| TabletToolType::Finger => {
let x = Fixed::from_f64(rect.x1() as f64 + (rect.width() as f64 * delta.x.x));
let y = Fixed::from_f64(rect.y1() as f64 + (rect.height() as f64 * delta.y.x));
(x, y)
}
};
tool.cursor.set_position(x, y);
}
tool.cursor.activate();
tool.tool_owner
.apply_changes(&tool, time_usec, Some(changes));
}
}
impl TabletTool {
fn for_each_pair(&self, n: &WlSurface, mut f: impl FnMut(&ZwpTabletV2, &ZwpTabletToolV2)) {
self.tablet.seat.tablet_for_each_seat(n, |s| {
let Some(tablet) = self.tablet.bindings.get(s) else {
return;
};
let Some(tool) = self.bindings.get(s) else {
return;
};
f(&tablet, &tool);
})
}
fn for_each_entered(&self, n: &WlSurface, mut f: impl FnMut(&ZwpTabletToolV2)) {
self.tablet.seat.tablet_for_each_seat(n, |s| {
let Some(tool) = self.bindings.get(s) else {
return;
};
if !tool.entered.get() {
return;
}
f(&tool);
})
}
pub fn surface_leave(&self, n: &WlSurface, time_usec: u64) {
let time = usec_to_msec(time_usec);
self.for_each_entered(n, |t| {
t.send_proximity_out();
t.send_frame(time);
})
}
pub fn surface_enter(&self, n: &WlSurface, time_usec: u64, x: Fixed, y: Fixed) {
let time = usec_to_msec(time_usec);
let mut serial = n.client.pending_serial();
self.for_each_pair(n, |tablet, tool| {
tool.send_proximity_in(serial.get(), tablet, n);
tool.send_motion(x, y);
tool.send_pressure(normalizeu(self.pressure.get()));
tool.send_distance(normalizeu(self.distance.get()));
tool.send_tilt(
Fixed::from_f64(self.tilt_x.get()),
Fixed::from_f64(self.tilt_y.get()),
);
tool.send_rotation(Fixed::from_f64(self.rotation.get()));
tool.send_slider(normalizei(self.slider.get()));
tool.send_frame(time);
})
}
pub fn surface_button(
&self,
n: &WlSurface,
time_usec: u64,
button: u32,
state: ToolButtonState,
) {
let time = usec_to_msec(time_usec);
let mut serial = n.client.pending_serial();
self.for_each_entered(n, |tool| {
tool.send_button(serial.get(), button, state);
tool.send_frame(time);
});
if state == ToolButtonState::Pressed {
if let Some(node) = n.get_focus_node(self.tablet.seat.id) {
self.tablet.seat.focus_node(node);
}
}
}
pub fn surface_apply_changes(
&self,
n: &WlSurface,
time_usec: u64,
changes: Option<&TabletToolChanges>,
x: Fixed,
y: Fixed,
) {
let mut serial = n.client.pending_serial();
let time = usec_to_msec(time_usec);
self.for_each_entered(n, |tool| {
if let Some(changes) = changes {
if let Some(val) = changes.down {
match val {
false => tool.send_up(),
true => tool.send_down(serial.get()),
}
}
if let Some(val) = changes.pressure {
tool.send_pressure(normalizeu(val));
}
if let Some(val) = changes.distance {
tool.send_distance(normalizeu(val));
}
if let Some(val) = changes.tilt {
tool.send_tilt(Fixed::from_f64(val.x), Fixed::from_f64(val.y));
}
if let Some(val) = changes.rotation {
tool.send_rotation(Fixed::from_f64(val));
}
if let Some(val) = changes.slider {
tool.send_slider(normalizei(val));
}
if let Some(val) = changes.wheel {
tool.send_wheel(Fixed::from_f64(val.degrees), val.clicks);
}
}
tool.send_motion(x, y);
tool.send_frame(time);
});
if let Some(changes) = changes {
if changes.down == Some(true) {
if let Some(node) = n.get_focus_node(self.tablet.seat.id) {
self.tablet.seat.focus_node(node);
}
}
}
}
}
impl TabletToolOpt {
pub fn get(&self) -> Option<Rc<TabletTool>> {
self.tool.get()
}
}