From 9b4f090dd3b8caa7c8d22c6ce957e2b839f1cb17 Mon Sep 17 00:00:00 2001 From: Murarth Date: Sun, 24 Nov 2019 12:51:38 -0700 Subject: [PATCH 1/4] X11: Report `CursorMoved` when touch event occurs --- CHANGELOG.md | 2 ++ src/platform_impl/linux/x11/event_processor.rs | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 43c609d072..8e00890af4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ - On X11, fix key modifiers being incorrectly reported. - On X11, fix window creation hanging when another window is fullscreen. - On Windows, fix focusing unfocused windows when switching from fullscreen to windowed. +- 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 2758aa3581..1b2bcf8eb7 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -956,10 +956,22 @@ impl EventProcessor { let dpi_factor = self.with_window(xev.event, |window| window.hidpi_factor()); if let Some(dpi_factor) = dpi_factor { + 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 + 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 { From 3c2db887066a49c5e98dcec462e45cdaf0c26246 Mon Sep 17 00:00:00 2001 From: Murarth Date: Sat, 7 Dec 2019 09:58:44 -0700 Subject: [PATCH 2/4] Only trigger CursorMoved events for the first touch ID --- .../linux/x11/event_processor.rs | 37 ++++++++++++++----- src/platform_impl/linux/x11/mod.rs | 1 + 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index e503e95357..b3e17d018f 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -25,6 +25,7 @@ pub(super) struct EventProcessor { pub(super) target: Rc>, pub(super) mod_keymap: ModifierKeymap, pub(super) device_mod_state: ModifierKeyState, + pub(super) first_touch: Option, } impl EventProcessor { @@ -958,21 +959,29 @@ 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 - callback(Event::WindowEvent { - window_id, - event: WindowEvent::CursorMoved { - device_id: mkdid(util::VIRTUAL_CORE_POINTER), - position: location, - modifiers, - }, - }); + // Mouse cursor position changes when touch events are received. + // Only the first concurrently active touch ID moves the mouse cursor. + if first_touch(&mut self.first_touch, id) { + if phase == TouchPhase::Ended { + self.first_touch = None; + } + + callback(Event::WindowEvent { + window_id, + event: WindowEvent::CursorMoved { + device_id: mkdid(util::VIRTUAL_CORE_POINTER), + position: location, + modifiers, + }, + }); + } callback(Event::WindowEvent { window_id, @@ -981,7 +990,7 @@ impl EventProcessor { phase, location, force: None, // TODO - id: xev.detail as u64, + id, }), }) } @@ -1195,3 +1204,11 @@ impl EventProcessor { } } } + +fn first_touch(m: &mut Option, id: u64) -> bool { + if m.is_none() { + *m = Some(id); + } + + *m == Some(id) +} diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index 25e8b07ac8..01808b7b88 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -193,6 +193,7 @@ impl EventLoop { xi2ext, mod_keymap, device_mod_state: Default::default(), + first_touch: None, }; // Register for device hotplug events From 0eb9d6337d84afb6e196be666869341f7eac1976 Mon Sep 17 00:00:00 2001 From: Murarth Date: Sat, 7 Dec 2019 15:58:42 -0700 Subject: [PATCH 3/4] Fix testing for current touch events --- .../linux/x11/event_processor.rs | 37 ++++++++++++------- src/platform_impl/linux/x11/mod.rs | 2 +- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index b3e17d018f..a8be4cedb6 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -1,4 +1,10 @@ -use std::{cell::RefCell, collections::HashMap, ptr, rc::Rc, slice}; +use std::{ + cell::RefCell, + collections::{HashMap, HashSet}, + ptr, + rc::Rc, + slice, +}; use libc::{c_char, c_int, c_long, c_uint, c_ulong}; @@ -12,7 +18,7 @@ use util::modifiers::{ModifierKeyState, ModifierKeymap}; use crate::{ dpi::{LogicalPosition, LogicalSize}, - event::{DeviceEvent, Event, KeyboardInput, ModifiersState, WindowEvent}, + event::{DeviceEvent, Event, KeyboardInput, ModifiersState, TouchPhase, WindowEvent}, event_loop::EventLoopWindowTarget as RootELW, }; @@ -25,7 +31,8 @@ pub(super) struct EventProcessor { pub(super) target: Rc>, pub(super) mod_keymap: ModifierKeymap, pub(super) device_mod_state: ModifierKeyState, - pub(super) first_touch: Option, + // Set of touch events currently in progress + pub(super) touch: HashSet, } impl EventProcessor { @@ -629,7 +636,7 @@ impl EventProcessor { ElementState::{Pressed, Released}, MouseButton::{Left, Middle, Other, Right}, MouseScrollDelta::LineDelta, - Touch, TouchPhase, + Touch, WindowEvent::{ AxisMotion, CursorEntered, CursorLeft, CursorMoved, Focused, MouseInput, MouseWheel, @@ -968,11 +975,7 @@ impl EventProcessor { // Mouse cursor position changes when touch events are received. // Only the first concurrently active touch ID moves the mouse cursor. - if first_touch(&mut self.first_touch, id) { - if phase == TouchPhase::Ended { - self.first_touch = None; - } - + if is_first_touch(&mut self.touch, id, phase) { callback(Event::WindowEvent { window_id, event: WindowEvent::CursorMoved { @@ -1205,10 +1208,18 @@ impl EventProcessor { } } -fn first_touch(m: &mut Option, id: u64) -> bool { - if m.is_none() { - *m = Some(id); +fn is_first_touch(m: &mut HashSet, id: u64, phase: TouchPhase) -> bool { + let is_first = m.is_empty(); + + match phase { + TouchPhase::Started => { + m.insert(id); + } + TouchPhase::Cancelled | TouchPhase::Ended => { + m.remove(&id); + } + _ => (), } - *m == Some(id) + is_first } diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index 01808b7b88..fe88a85ce2 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -193,7 +193,7 @@ impl EventLoop { xi2ext, mod_keymap, device_mod_state: Default::default(), - first_touch: None, + touch: Default::default(), }; // Register for device hotplug events From 104785f2891bbc8044654e7d3c83457dec288c10 Mon Sep 17 00:00:00 2001 From: Murarth Date: Sun, 8 Dec 2019 10:57:08 -0700 Subject: [PATCH 4/4] Fix first touch logic --- .../linux/x11/event_processor.rs | 31 ++++++++++--------- src/platform_impl/linux/x11/mod.rs | 3 +- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index 0ff39d601f..8c27eefa0d 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -1,9 +1,4 @@ -use std::{ - cell::RefCell, - collections::{HashMap, HashSet}, - rc::Rc, - slice, -}; +use std::{cell::RefCell, collections::HashMap, rc::Rc, slice}; use libc::{c_char, c_int, c_long, c_uint, c_ulong}; @@ -32,8 +27,9 @@ pub(super) struct EventProcessor { pub(super) target: Rc>, pub(super) mod_keymap: ModifierKeymap, pub(super) device_mod_state: ModifierKeyState, - // Set of touch events currently in progress - pub(super) touch: HashSet, + // Number of touch events currently in progress + pub(super) num_touch: u32, + pub(super) first_touch: Option, } impl EventProcessor { @@ -980,7 +976,8 @@ impl EventProcessor { // 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.touch, id, phase) { + if is_first_touch(&mut self.first_touch, &mut self.num_touch, id, phase) + { callback(Event::WindowEvent { window_id, event: WindowEvent::CursorMoved { @@ -1242,18 +1239,22 @@ impl EventProcessor { } } -fn is_first_touch(m: &mut HashSet, id: u64, phase: TouchPhase) -> bool { - let is_first = m.is_empty(); - +fn is_first_touch(first: &mut Option, num: &mut u32, id: u64, phase: TouchPhase) -> bool { match phase { TouchPhase::Started => { - m.insert(id); + if *num == 0 { + *first = Some(id); + } + *num += 1; } TouchPhase::Cancelled | TouchPhase::Ended => { - m.remove(&id); + if *first == Some(id) { + *first = None; + } + *num = num.saturating_sub(1); } _ => (), } - is_first + *first == Some(id) } diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index 228a8b00bb..71e538dab7 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -199,7 +199,8 @@ impl EventLoop { xi2ext, mod_keymap, device_mod_state: Default::default(), - touch: Default::default(), + num_touch: 0, + first_touch: None, }; // Register for device hotplug events