Skip to content
This repository has been archived by the owner on Jul 11, 2023. It is now read-only.

Commit

Permalink
Add basic touch support (pointer emulation)
Browse files Browse the repository at this point in the history
iced doesn't know what touch is yet, so this is all we can do.
Click-on-release works great for the dock actually!
  • Loading branch information
valpackett committed Aug 22, 2020
1 parent 18614a2 commit 8017f64
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 11 deletions.
30 changes: 20 additions & 10 deletions shell/src/dock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,8 @@ impl DockApp {
}

pub struct Dock {
shown: bool,
is_pointed: bool,
is_touched: bool,
seat: wl_seat::WlSeat,
toplevels: ToplevelStates,
apps: Vec<DockApp>,
Expand All @@ -162,7 +163,8 @@ pub struct Dock {
impl Dock {
pub fn new(seat: wl_seat::WlSeat, toplevels: ToplevelStates) -> Dock {
Dock {
shown: false,
is_pointed: false,
is_touched: false,
seat,
toplevels,
apps: Vec::new(),
Expand Down Expand Up @@ -248,7 +250,7 @@ impl IcedSurface for Dock {
let mut col = Column::new().width(Length::Fill);

let dock_width = self.width();
if let Some(appi) = if self.shown { self.hovered_app } else { None } {
if let Some(appi) = if self.is_pointed || self.is_touched { self.hovered_app } else { None } {
let our_center = self.center_of_app(appi);
let toplevels = self.toplevels.borrow();
let appid = self.apps[appi].id();
Expand Down Expand Up @@ -303,7 +305,7 @@ impl IcedSurface for Dock {
// XXX: removing the icons from the output causes them to be unloaded
// so for now we just make the dock invisible

// if self.shown {
// if self.is_pointed || self.is_touched {
let toplevels = self.toplevels.borrow();
let row = self.apps.iter_mut().enumerate().fold(
Row::new().align_items(Align::Center).spacing(DOCK_PADDING),
Expand All @@ -321,9 +323,9 @@ impl IcedSurface for Dock {
.height(Length::Shrink)
.center_x()
.center_y()
.padding(if self.shown { DOCK_PADDING } else { 0 }),
.padding(if self.is_pointed || self.is_touched { DOCK_PADDING } else { 0 }),
)
.width(if self.shown {
.width(if self.is_pointed || self.is_touched {
Length::Fill
} else {
Length::Units(0)
Expand Down Expand Up @@ -369,7 +371,7 @@ impl IcedSurface for Dock {
height: BAR_HEIGHT as _,
};
let mut result = vec![bar];
if self.shown {
if self.is_pointed || self.is_touched {
let dock_width = self.width() as _;
result.push(Rectangle {
x: (width - dock_width) / 2,
Expand All @@ -378,7 +380,7 @@ impl IcedSurface for Dock {
height: (BAR_HEIGHT + DOCK_AND_GAP_HEIGHT) as _,
});
}
if let Some(appi) = if self.shown { self.hovered_app } else { None } {
if let Some(appi) = if self.is_pointed || self.is_touched { self.hovered_app } else { None } {
let toplevels_height = 200; // TODO: calc
let dock_width = self.width() as i32;
let our_center = self.center_of_app(appi) as i32;
Expand Down Expand Up @@ -427,11 +429,19 @@ impl IcedSurface for Dock {
}

async fn on_pointer_enter(&mut self) {
self.shown = true;
self.is_pointed = true;
}

async fn on_pointer_leave(&mut self) {
self.shown = false;
self.is_pointed = false;
self.hovered_app = None;
}

async fn on_touch_enter(&mut self) {
self.is_touched = true;
}

async fn on_touch_leave(&mut self) {
self.is_touched = false;
}
}
64 changes: 64 additions & 0 deletions wstk/src/iced.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ pub trait IcedSurface {

async fn on_pointer_enter(&mut self) {}
async fn on_pointer_leave(&mut self) {}
async fn on_touch_enter(&mut self) {}
async fn on_touch_leave(&mut self) {}
}

pub struct IcedInstance<T> {
Expand All @@ -37,6 +39,8 @@ pub struct IcedInstance<T> {
scale: i32,
leave_timeout: Option<future::Fuse<Pin<Box<dyn Future<Output = ()> + Send + 'static>>>>,
prev_input_region: Option<Vec<Rectangle<i32>>>,
touch_point: Option<i32>,
touch_leave: bool,

// iced render state
cache: Cache,
Expand Down Expand Up @@ -76,6 +80,8 @@ impl<T: DesktopSurface + IcedSurface> IcedInstance<T> {
scale: 1,
leave_timeout: None,
prev_input_region: None,
touch_point: None,
touch_leave: false,
cache: Cache::new(),
size: Size::new(0.0, 0.0),
cursor_position: Point::default(),
Expand Down Expand Up @@ -273,9 +279,66 @@ impl<T: DesktopSurface + IcedSurface> IcedInstance<T> {
}
}

async fn on_touch_event(&mut self, event: Arc<wl_touch::Event>) {
match &*event {
wl_touch::Event::Down { surface, id, x, y, .. } => {
if self.parent.wl_surface.detach() != *surface {
return;
}
if self.touch_point.is_some() {
return;
}
self.touch_point = Some(*id);
self.ptr_active = true;
self.leave_timeout = None;
self.cursor_position = Point::new(*x as _, *y as _);
self.queue
.push(iced_native::Event::Mouse(mouse::Event::CursorMoved {
x: *x as _,
y: *y as _,
}));
self.surface.on_touch_enter().await;
},
wl_touch::Event::Motion { id, x, y, .. } => {
if self.touch_point != Some(*id) {
return;
}
self.cursor_position = Point::new(*x as _, *y as _);
self.queue
.push(iced_native::Event::Mouse(mouse::Event::CursorMoved {
x: *x as _,
y: *y as _,
}));
},
wl_touch::Event::Up { id, .. } => {
if self.touch_point != Some(*id) {
return;
}
self.touch_point = None;
self.queue.push(iced_native::Event::Mouse(
mouse::Event::ButtonPressed(mouse::Button::Left)
));
self.queue.push(iced_native::Event::Mouse(
mouse::Event::ButtonReleased(mouse::Button::Left)
));
self.touch_leave = true;
}
wl_touch::Event::Frame { .. } => {
self.render().await;
if self.touch_leave {
self.surface.on_touch_leave().await;
self.touch_leave = false;
self.render().await;
}
}
e => eprintln!("{:?}", e),
}
}

pub async fn run(&mut self, ext_evt_src: &mut (impl Stream<Item = T::ExternalEvent> + Unpin)) {
let seat = &self.parent.env.get_all_seats()[0];
let mut ptr_events = wayland_event_chan(&seat.get_pointer());
let mut touch_events = wayland_event_chan(&seat.get_touch());
let mut layer_events = wayland_event_chan(&self.parent.layer_surface);

loop {
Expand All @@ -288,6 +351,7 @@ impl<T: DesktopSurface + IcedSurface> IcedInstance<T> {
futures::select! {
ev = layer_events.next() => if let Some(event) = ev { self.on_layer_event(event).await },
ev = ptr_events.next() => if let Some(event) = ev { self.on_pointer_event(event).await },
ev = touch_events.next() => if let Some(event) = ev { self.on_touch_event(event).await },
sc = self.parent.scale_rx.next() => if let Some(scale) = sc { self.on_scale(scale).await },
ev = ext_evt_src.next().fuse() => if let Some(event) = ev {
self.surface.react(event).await;
Expand Down
2 changes: 1 addition & 1 deletion wstk/src/surfaces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pub use smithay_client_toolkit::{
get_surface_scale_factor,
reexports::{
client::{
protocol::{wl_compositor, wl_pointer, wl_region, wl_seat, wl_surface},
protocol::{wl_compositor, wl_pointer, wl_region, wl_seat, wl_surface, wl_touch},
Attached, ConnectError, Display, EventQueue, Interface, Main, Proxy,
},
protocols::wlr::unstable::foreign_toplevel::v1::client::{
Expand Down

0 comments on commit 8017f64

Please sign in to comment.