diff --git a/CHANGELOG.md b/CHANGELOG.md index 2271ec53..6c39ecdf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # Unreleased +- On Wayland, fix coordinates in touch events when scale factor isn't 1 + # 0.21.0 (2020-02-04) - On Windows, fixed "error: linking with `link.exe` failed: exit code: 1120" error on older versions of windows. diff --git a/src/platform_impl/linux/wayland/pointer.rs b/src/platform_impl/linux/wayland/pointer.rs index 2ba6c934..5f93099f 100644 --- a/src/platform_impl/linux/wayland/pointer.rs +++ b/src/platform_impl/linux/wayland/pointer.rs @@ -1,5 +1,6 @@ use std::sync::{Arc, Mutex}; +use crate::dpi::LogicalPosition; use crate::event::{ DeviceEvent, ElementState, ModifiersState, MouseButton, MouseScrollDelta, TouchPhase, WindowEvent, @@ -76,13 +77,16 @@ pub fn implement_pointer( }, wid, ); + + let position = LogicalPosition::new(surface_x, surface_y) + .to_physical(scale_factor); + sink.send_window_event( WindowEvent::CursorMoved { device_id: crate::event::DeviceId( crate::platform_impl::DeviceId::Wayland(DeviceId), ), - position: (surface_x * scale_factor, surface_y * scale_factor) - .into(), + position, modifiers: modifiers_tracker.lock().unwrap().clone(), }, wid, @@ -109,15 +113,18 @@ pub fn implement_pointer( .. } => { if let Some(surface) = mouse_focus.as_ref() { - let scale_factor = surface::get_dpi_factor(&surface) as f64; let wid = make_wid(surface); + + let scale_factor = surface::get_dpi_factor(&surface) as f64; + let position = LogicalPosition::new(surface_x, surface_y) + .to_physical(scale_factor); + sink.send_window_event( WindowEvent::CursorMoved { device_id: crate::event::DeviceId( crate::platform_impl::DeviceId::Wayland(DeviceId), ), - position: (surface_x * scale_factor, surface_y * scale_factor) - .into(), + position, modifiers: modifiers_tracker.lock().unwrap().clone(), }, wid, diff --git a/src/platform_impl/linux/wayland/touch.rs b/src/platform_impl/linux/wayland/touch.rs index 803ea624..ce4e32c2 100644 --- a/src/platform_impl/linux/wayland/touch.rs +++ b/src/platform_impl/linux/wayland/touch.rs @@ -1,17 +1,22 @@ use std::sync::{Arc, Mutex}; +use crate::dpi::LogicalPosition; use crate::event::{TouchPhase, WindowEvent}; -use super::{event_loop::EventsSink, window::WindowStore, DeviceId, WindowId}; +use super::{event_loop::EventsSink, make_wid, window::WindowStore, DeviceId}; + +use smithay_client_toolkit::surface; use smithay_client_toolkit::reexports::client::protocol::{ wl_seat, + wl_surface::WlSurface, wl_touch::{Event as TouchEvent, WlTouch}, }; +// location is in logical coordinates. struct TouchPoint { - wid: WindowId, - location: (f64, f64), + surface: WlSurface, + position: LogicalPosition, id: i32, } @@ -31,21 +36,24 @@ pub(crate) fn implement_touch( } => { let wid = store.find_wid(&surface); if let Some(wid) = wid { + let scale_factor = surface::get_dpi_factor(&surface) as f64; + let position = LogicalPosition::new(x, y); + sink.send_window_event( WindowEvent::Touch(crate::event::Touch { device_id: crate::event::DeviceId( crate::platform_impl::DeviceId::Wayland(DeviceId), ), phase: TouchPhase::Started, - location: (x, y).into(), + location: position.to_physical(scale_factor), force: None, // TODO id: id as u64, }), wid, ); pending_ids.push(TouchPoint { - wid, - location: (x, y), + surface, + position, id, }); } @@ -54,52 +62,63 @@ pub(crate) fn implement_touch( let idx = pending_ids.iter().position(|p| p.id == id); if let Some(idx) = idx { let pt = pending_ids.remove(idx); + + let scale_factor = surface::get_dpi_factor(&pt.surface) as f64; + let location = pt.position.to_physical(scale_factor); + sink.send_window_event( WindowEvent::Touch(crate::event::Touch { device_id: crate::event::DeviceId( crate::platform_impl::DeviceId::Wayland(DeviceId), ), phase: TouchPhase::Ended, - location: pt.location.into(), + location, force: None, // TODO id: id as u64, }), - pt.wid, + make_wid(&pt.surface), ); } } TouchEvent::Motion { id, x, y, .. } => { let pt = pending_ids.iter_mut().find(|p| p.id == id); if let Some(pt) = pt { - pt.location = (x, y); + pt.position = LogicalPosition::new(x, y); + + let scale_factor = surface::get_dpi_factor(&pt.surface) as f64; + let location = pt.position.to_physical(scale_factor); + sink.send_window_event( WindowEvent::Touch(crate::event::Touch { device_id: crate::event::DeviceId( crate::platform_impl::DeviceId::Wayland(DeviceId), ), phase: TouchPhase::Moved, - location: (x, y).into(), + location, force: None, // TODO id: id as u64, }), - pt.wid, + make_wid(&pt.surface), ); } } TouchEvent::Frame => (), TouchEvent::Cancel => { for pt in pending_ids.drain(..) { + let scale_factor = surface::get_dpi_factor(&pt.surface) as f64; + let location = pt.position.to_physical(scale_factor); + sink.send_window_event( WindowEvent::Touch(crate::event::Touch { device_id: crate::event::DeviceId( crate::platform_impl::DeviceId::Wayland(DeviceId), ), phase: TouchPhase::Cancelled, - location: pt.location.into(), + location, force: None, // TODO id: pt.id as u64, }), - pt.wid, + make_wid(&pt.surface), ); } }