X11: Report CursorMoved when touch event occurs (#1297)

* X11: Report `CursorMoved` when touch event occurs

* Only trigger CursorMoved events for the first touch ID

* Fix testing for current touch events

* Fix first touch logic
This commit is contained in:
Murarth 2019-12-11 17:23:55 -07:00 committed by GitHub
parent e5291c9e28
commit 1f81e5c872
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 3 deletions

View file

@ -15,6 +15,8 @@
- Add `is_synthetic` field to `WindowEvent` variant `KeyboardInput`, - Add `is_synthetic` field to `WindowEvent` variant `KeyboardInput`,
indicating that the event is generated by winit. 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, 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) # 0.20.0 Alpha 4 (2019-10-18)

View file

@ -12,7 +12,9 @@ use util::modifiers::{ModifierKeyState, ModifierKeymap};
use crate::{ use crate::{
dpi::{LogicalPosition, LogicalSize}, dpi::{LogicalPosition, LogicalSize},
event::{DeviceEvent, ElementState, Event, KeyboardInput, ModifiersState, WindowEvent}, event::{
DeviceEvent, ElementState, Event, KeyboardInput, ModifiersState, TouchPhase, WindowEvent,
},
event_loop::EventLoopWindowTarget as RootELW, event_loop::EventLoopWindowTarget as RootELW,
}; };
@ -25,6 +27,9 @@ pub(super) struct EventProcessor<T: 'static> {
pub(super) target: Rc<RootELW<T>>, pub(super) target: Rc<RootELW<T>>,
pub(super) mod_keymap: ModifierKeymap, pub(super) mod_keymap: ModifierKeymap,
pub(super) device_mod_state: ModifierKeyState, pub(super) device_mod_state: ModifierKeyState,
// Number of touch events currently in progress
pub(super) num_touch: u32,
pub(super) first_touch: Option<u64>,
} }
impl<T: 'static> EventProcessor<T> { impl<T: 'static> EventProcessor<T> {
@ -620,7 +625,7 @@ impl<T: 'static> EventProcessor<T> {
ElementState::{Pressed, Released}, ElementState::{Pressed, Released},
MouseButton::{Left, Middle, Other, Right}, MouseButton::{Left, Middle, Other, Right},
MouseScrollDelta::LineDelta, MouseScrollDelta::LineDelta,
Touch, TouchPhase, Touch,
WindowEvent::{ WindowEvent::{
AxisMotion, CursorEntered, CursorLeft, CursorMoved, Focused, MouseInput, AxisMotion, CursorEntered, CursorLeft, CursorMoved, Focused, MouseInput,
MouseWheel, MouseWheel,
@ -962,10 +967,27 @@ impl<T: 'static> EventProcessor<T> {
let dpi_factor = let dpi_factor =
self.with_window(xev.event, |window| window.hidpi_factor()); self.with_window(xev.event, |window| window.hidpi_factor());
if let Some(dpi_factor) = dpi_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( let location = LogicalPosition::from_physical(
(xev.event_x as f64, xev.event_y as f64), (xev.event_x as f64, xev.event_y as f64),
dpi_factor, 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 { callback(Event::WindowEvent {
window_id, window_id,
event: WindowEvent::Touch(Touch { event: WindowEvent::Touch(Touch {
@ -973,7 +995,7 @@ impl<T: 'static> EventProcessor<T> {
phase, phase,
location, location,
force: None, // TODO force: None, // TODO
id: xev.detail as u64, id,
}), }),
}) })
} }
@ -1216,3 +1238,23 @@ impl<T: 'static> EventProcessor<T> {
} }
} }
} }
fn is_first_touch(first: &mut Option<u64>, 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)
}

View file

@ -199,6 +199,8 @@ impl<T: 'static> EventLoop<T> {
xi2ext, xi2ext,
mod_keymap, mod_keymap,
device_mod_state: Default::default(), device_mod_state: Default::default(),
num_touch: 0,
first_touch: None,
}; };
// Register for device hotplug events // Register for device hotplug events