Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,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)

Expand Down
48 changes: 45 additions & 3 deletions src/platform_impl/linux/x11/event_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};

Expand All @@ -25,6 +27,9 @@ pub(super) struct EventProcessor<T: 'static> {
pub(super) target: Rc<RootELW<T>>,
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<u64>,
}

impl<T: 'static> EventProcessor<T> {
Expand Down Expand Up @@ -620,7 +625,7 @@ impl<T: 'static> EventProcessor<T> {
ElementState::{Pressed, Released},
MouseButton::{Left, Middle, Other, Right},
MouseScrollDelta::LineDelta,
Touch, TouchPhase,
Touch,
WindowEvent::{
AxisMotion, CursorEntered, CursorLeft, CursorMoved, Focused, MouseInput,
MouseWheel,
Expand Down Expand Up @@ -962,18 +967,35 @@ impl<T: 'static> EventProcessor<T> {
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 {
device_id: mkdid(xev.deviceid),
phase,
location,
force: None, // TODO
id: xev.detail as u64,
id,
}),
})
}
Expand Down Expand Up @@ -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;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding is that this is correct, but unnecessary: if num == 0 then first == Some(id) is never evaluated (except on TouchPhase::Ended for the last event, when the above ids are still valid). As soon as the next event starts, first is re-assigned. Thus in my version I didn't bother using an Option here.

}
*num = num.saturating_sub(1);
}
_ => (),
}

*first == Some(id)
}
2 changes: 2 additions & 0 deletions src/platform_impl/linux/x11/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,8 @@ impl<T: 'static> EventLoop<T> {
xi2ext,
mod_keymap,
device_mod_state: Default::default(),
num_touch: 0,
first_touch: None,
};

// Register for device hotplug events
Expand Down