diff --git a/CHANGELOG.md b/CHANGELOG.md index 1de068a8..801eb116 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ - Add `is_synthetic` field to `WindowEvent` variant `KeyboardInput`, indicating that the event is generated by winit. - On X11, generate synthetic key events for keys held when a window gains or loses focus. +- On X11, issue a `CursorMoved` event when a `Touch` event occurs, + as X11 implicitly moves the cursor for such events. # 0.20.0 Alpha 4 (2019-10-18) diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index 6f544726..8c27eefa 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -12,7 +12,9 @@ use util::modifiers::{ModifierKeyState, ModifierKeymap}; use crate::{ dpi::{LogicalPosition, LogicalSize}, - event::{DeviceEvent, ElementState, Event, KeyboardInput, ModifiersState, WindowEvent}, + event::{ + DeviceEvent, ElementState, Event, KeyboardInput, ModifiersState, TouchPhase, WindowEvent, + }, event_loop::EventLoopWindowTarget as RootELW, }; @@ -25,6 +27,9 @@ pub(super) struct EventProcessor { pub(super) target: Rc>, pub(super) mod_keymap: ModifierKeymap, pub(super) device_mod_state: ModifierKeyState, + // Number of touch events currently in progress + pub(super) num_touch: u32, + pub(super) first_touch: Option, } impl EventProcessor { @@ -620,7 +625,7 @@ impl EventProcessor { ElementState::{Pressed, Released}, MouseButton::{Left, Middle, Other, Right}, MouseScrollDelta::LineDelta, - Touch, TouchPhase, + Touch, WindowEvent::{ AxisMotion, CursorEntered, CursorLeft, CursorMoved, Focused, MouseInput, MouseWheel, @@ -962,10 +967,27 @@ impl EventProcessor { let dpi_factor = self.with_window(xev.event, |window| window.hidpi_factor()); if let Some(dpi_factor) = dpi_factor { + let id = xev.detail as u64; + let modifiers = self.device_mod_state.modifiers(); let location = LogicalPosition::from_physical( (xev.event_x as f64, xev.event_y as f64), dpi_factor, ); + + // Mouse cursor position changes when touch events are received. + // Only the first concurrently active touch ID moves the mouse cursor. + if is_first_touch(&mut self.first_touch, &mut self.num_touch, id, phase) + { + callback(Event::WindowEvent { + window_id, + event: WindowEvent::CursorMoved { + device_id: mkdid(util::VIRTUAL_CORE_POINTER), + position: location, + modifiers, + }, + }); + } + callback(Event::WindowEvent { window_id, event: WindowEvent::Touch(Touch { @@ -973,7 +995,7 @@ impl EventProcessor { phase, location, force: None, // TODO - id: xev.detail as u64, + id, }), }) } @@ -1216,3 +1238,23 @@ impl EventProcessor { } } } + +fn is_first_touch(first: &mut Option, num: &mut u32, id: u64, phase: TouchPhase) -> bool { + match phase { + TouchPhase::Started => { + if *num == 0 { + *first = Some(id); + } + *num += 1; + } + TouchPhase::Cancelled | TouchPhase::Ended => { + if *first == Some(id) { + *first = None; + } + *num = num.saturating_sub(1); + } + _ => (), + } + + *first == Some(id) +} diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index 8cfc3556..71e538da 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -199,6 +199,8 @@ impl EventLoop { xi2ext, mod_keymap, device_mod_state: Default::default(), + num_touch: 0, + first_touch: None, }; // Register for device hotplug events