Skip to content

Commit

Permalink
ei: implement ei_touchscreen v2
Browse files Browse the repository at this point in the history
  • Loading branch information
mahkoh committed Nov 27, 2024
1 parent 723608c commit e500b3d
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 20 deletions.
7 changes: 4 additions & 3 deletions src/ei/ei_ifs/ei_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use {
leaks::Tracker,
rect::Rect,
scale::Scale,
utils::syncqueue::SyncQueue,
utils::{copyhashmap::CopyHashMap, syncqueue::SyncQueue},
wire_ei::{
ei_device::{
ClientFrame, ClientStartEmulating, ClientStopEmulating, Destroyed, DeviceType,
Expand All @@ -37,7 +37,7 @@ pub struct EiDevice {
pub seat: Rc<EiSeat>,

pub button_changes: SyncQueue<(u32, KeyState)>,
pub touch_changes: SyncQueue<(u32, TouchChange)>,
pub touch_changes: CopyHashMap<u32, TouchChange>,
pub scroll_px: [Cell<Option<f32>>; 2],
pub scroll_v120: [Cell<Option<i32>>; 2],
pub scroll_stop: [Cell<Option<bool>>; 2],
Expand Down Expand Up @@ -219,7 +219,7 @@ impl EiDeviceRequestHandler for EiDevice {
}
}
if self.touch_changes.is_not_empty() {
while let Some((touch_id, change)) = self.touch_changes.pop() {
for (touch_id, change) in self.touch_changes.lock().drain() {
let id = touch_id as i32;
match change {
TouchChange::Down(x, y) => {
Expand All @@ -233,6 +233,7 @@ impl EiDeviceRequestHandler for EiDevice {
seat.touch_motion_at(time, id, x, y);
}
TouchChange::Up => seat.touch_up(time, id),
TouchChange::Cancel => seat.touch_cancel(time, id),
}
}
seat.touch_frame(time);
Expand Down
12 changes: 12 additions & 0 deletions src/ei/ei_ifs/ei_seat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,18 @@ impl EiSeat {
}
}

pub fn handle_touch_cancel(&self, id: u32) {
if self.is_sender() {
return;
}
if let Some(b) = self.touchscreen.get() {
if self.client.versions.ei_touchscreen() >= EiVersion(2) {
b.send_cancel(id);
}
b.send_up(id);
}
}

pub fn handle_touch_frame(&self, time_usec: u64) {
if self.is_sender() {
return;
Expand Down
62 changes: 47 additions & 15 deletions src/ei/ei_ifs/ei_touchscreen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@ use {
},
fixed::Fixed,
leaks::Tracker,
utils::clonecell::UnsafeCellCloneSafe,
wire_ei::{
ei_touchscreen::{
ClientDown, ClientMotion, ClientUp, EiTouchscreenRequestHandler, Release,
ServerDown, ServerMotion, ServerUp,
ClientCancel, ClientDown, ClientMotion, ClientUp, EiTouchscreenRequestHandler,
Release, ServerCancel, ServerDown, ServerMotion, ServerUp,
},
EiTouchscreenId,
},
},
std::rc::Rc,
std::{collections::hash_map::Entry, rc::Rc},
thiserror::Error,
};

Expand All @@ -32,8 +33,11 @@ pub enum TouchChange {
Down(f32, f32),
Motion(f32, f32),
Up,
Cancel,
}

unsafe impl UnsafeCellCloneSafe for TouchChange {}

ei_device_interface!(EiTouchscreen, ei_touchscreen, touchscreen);

impl EiTouchscreen {
Expand Down Expand Up @@ -61,6 +65,37 @@ impl EiTouchscreen {
touchid,
});
}

pub fn send_cancel(&self, touchid: u32) {
self.client.event(ServerCancel {
self_id: self.id,
touchid,
});
}

fn set_client_event(&self, touchid: u32, event: TouchChange) -> Result<(), EiTouchscreenError> {
match self.device.touch_changes.lock().entry(touchid) {
Entry::Occupied(mut o) => {
use TouchChange::*;
match (o.get(), event) {
(Motion(_, _), Motion(_, _))
| (Down(_, _), Down(_, _))
| (Up, Up)
| (Cancel, Cancel)
| (Up, Cancel) => {
o.insert(event);
Ok(())
}
(Cancel, Up) => Ok(()),
_ => Err(EiTouchscreenError::InvalidEventCombination),
}
}
Entry::Vacant(v) => {
v.insert(event);
Ok(())
}
}
}
}

impl EiTouchscreenRequestHandler for EiTouchscreen {
Expand All @@ -72,24 +107,19 @@ impl EiTouchscreenRequestHandler for EiTouchscreen {
}

fn client_down(&self, req: ClientDown, _slf: &Rc<Self>) -> Result<(), Self::Error> {
self.device
.touch_changes
.push((req.touchid, TouchChange::Down(req.x, req.y)));
Ok(())
self.set_client_event(req.touchid, TouchChange::Down(req.x, req.y))
}

fn client_motion(&self, req: ClientMotion, _slf: &Rc<Self>) -> Result<(), Self::Error> {
self.device
.touch_changes
.push((req.touchid, TouchChange::Motion(req.x, req.y)));
Ok(())
self.set_client_event(req.touchid, TouchChange::Motion(req.x, req.y))
}

fn client_up(&self, req: ClientUp, _slf: &Rc<Self>) -> Result<(), Self::Error> {
self.device
.touch_changes
.push((req.touchid, TouchChange::Up));
Ok(())
self.set_client_event(req.touchid, TouchChange::Up)
}

fn client_cancel(&self, req: ClientCancel, _slf: &Rc<Self>) -> Result<(), Self::Error> {
self.set_client_event(req.touchid, TouchChange::Cancel)
}
}

Expand All @@ -104,5 +134,7 @@ impl EiObject for EiTouchscreen {}
pub enum EiTouchscreenError {
#[error(transparent)]
EiClientError(Box<EiClientError>),
#[error("Touch frame contains an invalid combination of events")]
InvalidEventCombination,
}
efrom!(EiTouchscreenError, EiClientError);
4 changes: 2 additions & 2 deletions src/ifs/wl_seat/event_handling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -761,9 +761,9 @@ impl WlSeatGlobal {
self.touch_owner.motion(self, time_usec, id, x, y);
}

fn touch_cancel(self: &Rc<Self>, time_usec: u64, id: i32) {
pub fn touch_cancel(self: &Rc<Self>, time_usec: u64, id: i32) {
self.for_each_ei_seat(|ei_seat| {
ei_seat.handle_touch_up(id as _);
ei_seat.handle_touch_cancel(id as _);
});
self.state.for_each_seat_tester(|t| {
t.send_touch_cancel(self.id, time_usec, id);
Expand Down
1 change: 1 addition & 0 deletions src/utils/syncqueue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ impl<T> SyncQueue<T> {
unsafe { self.el.get().deref_mut().is_empty() }
}

#[expect(dead_code)]
pub fn is_not_empty(&self) -> bool {
!self.is_empty()
}
Expand Down
8 changes: 8 additions & 0 deletions wire-ei/ei_touchscreen.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ request client_up (sender) {
touchid: u32,
}

request client_cancel (sender, since = 2) {
touchid: u32,
}

event destroyed {
serial: u32,
}
Expand All @@ -36,3 +40,7 @@ event server_motion (receiver) {
event server_up (receiver) {
touchid: u32,
}

event server_cancel (receiver, since = 2) {
touchid: u32,
}

0 comments on commit e500b3d

Please sign in to comment.