api: overhaul pointer API
- Rename `CursorMoved` to `PointerMoved`. - Rename `CursorEntered` to `PointerEntered`. - Rename `CursorLeft` to `PointerLeft`. - Rename `MouseInput` to `PointerButton`. - Add `position` to every `PointerEvent`. - Remove `Touch`, which is folded into the `Pointer*` events. - New `PointerType` added to `PointerEntered` and `PointerLeft`, signifying which pointer type is the source of this event. - New `PointerSource` added to `PointerMoved`, similar to `PointerType` but holding additional data. - New `ButtonSource` added to `PointerButton`, similar to `PointerType` but holding pointer type specific buttons. Use `ButtonSource::mouse_button()` to easily normalize any pointer button type to a generic mouse button. - In the same spirit rename `DeviceEvent::MouseMotion` to `PointerMotion`. - Remove `Force::Calibrated::altitude_angle`. Fixes #3833. Fixes #883. Fixes #336. Co-authored-by: Kirill Chibisov <contact@kchibisov.com>
This commit is contained in:
parent
32cd1ad9a7
commit
eccd9e415d
25 changed files with 1236 additions and 869 deletions
|
|
@ -22,8 +22,8 @@ use xkbcommon_dl::xkb_mod_mask_t;
|
|||
|
||||
use crate::dpi::{PhysicalPosition, PhysicalSize};
|
||||
use crate::event::{
|
||||
DeviceEvent, ElementState, Event, Ime, MouseButton, MouseScrollDelta, RawKeyEvent,
|
||||
SurfaceSizeWriter, Touch, TouchPhase, WindowEvent,
|
||||
ButtonSource, DeviceEvent, ElementState, Event, Ime, MouseButton, MouseScrollDelta,
|
||||
PointerKind, PointerSource, RawKeyEvent, SurfaceSizeWriter, TouchPhase, WindowEvent,
|
||||
};
|
||||
use crate::keyboard::ModifiersState;
|
||||
use crate::platform_impl::common::xkb::{self, XkbState};
|
||||
|
|
@ -238,15 +238,8 @@ impl EventProcessor {
|
|||
self.xinput2_unfocused(xev, &mut callback);
|
||||
},
|
||||
xinput2::XI_TouchBegin | xinput2::XI_TouchUpdate | xinput2::XI_TouchEnd => {
|
||||
let phase = match evtype {
|
||||
xinput2::XI_TouchBegin => TouchPhase::Started,
|
||||
xinput2::XI_TouchUpdate => TouchPhase::Moved,
|
||||
xinput2::XI_TouchEnd => TouchPhase::Ended,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let xev: &XIDeviceEvent = unsafe { xev.as_event() };
|
||||
self.xinput2_touch(xev, phase, &mut callback);
|
||||
self.xinput2_touch(xev, evtype, &mut callback);
|
||||
},
|
||||
xinput2::XI_RawButtonPress | xinput2::XI_RawButtonRelease => {
|
||||
let state = match evtype {
|
||||
|
|
@ -1025,16 +1018,27 @@ impl EventProcessor {
|
|||
return;
|
||||
}
|
||||
|
||||
let position = PhysicalPosition::new(event.event_x, event.event_y);
|
||||
|
||||
let event = match event.detail as u32 {
|
||||
xlib::Button1 => {
|
||||
WindowEvent::MouseInput { device_id, state, button: MouseButton::Left }
|
||||
xlib::Button1 => WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state,
|
||||
position,
|
||||
button: MouseButton::Left.into(),
|
||||
},
|
||||
xlib::Button2 => {
|
||||
WindowEvent::MouseInput { device_id, state, button: MouseButton::Middle }
|
||||
xlib::Button2 => WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state,
|
||||
position,
|
||||
button: MouseButton::Middle.into(),
|
||||
},
|
||||
|
||||
xlib::Button3 => {
|
||||
WindowEvent::MouseInput { device_id, state, button: MouseButton::Right }
|
||||
xlib::Button3 => WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state,
|
||||
position,
|
||||
button: MouseButton::Right.into(),
|
||||
},
|
||||
|
||||
// Suppress emulated scroll wheel clicks, since we handle the real motion events for
|
||||
|
|
@ -1052,10 +1056,25 @@ impl EventProcessor {
|
|||
},
|
||||
phase: TouchPhase::Moved,
|
||||
},
|
||||
8 => WindowEvent::MouseInput { device_id, state, button: MouseButton::Back },
|
||||
8 => WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state,
|
||||
position,
|
||||
button: MouseButton::Back.into(),
|
||||
},
|
||||
|
||||
9 => WindowEvent::MouseInput { device_id, state, button: MouseButton::Forward },
|
||||
x => WindowEvent::MouseInput { device_id, state, button: MouseButton::Other(x as u16) },
|
||||
9 => WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state,
|
||||
position,
|
||||
button: MouseButton::Forward.into(),
|
||||
},
|
||||
x => WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state,
|
||||
position,
|
||||
button: MouseButton::Other(x as u16).into(),
|
||||
},
|
||||
};
|
||||
|
||||
let event = Event::WindowEvent { window_id, event };
|
||||
|
|
@ -1084,7 +1103,11 @@ impl EventProcessor {
|
|||
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::CursorMoved { device_id, position },
|
||||
event: WindowEvent::PointerMoved {
|
||||
device_id,
|
||||
position,
|
||||
source: PointerSource::Mouse,
|
||||
},
|
||||
};
|
||||
callback(&self.target, event);
|
||||
} else if cursor_moved.is_none() {
|
||||
|
|
@ -1167,13 +1190,13 @@ impl EventProcessor {
|
|||
let device_id = Some(device_id);
|
||||
let position = PhysicalPosition::new(event.event_x, event.event_y);
|
||||
|
||||
let event =
|
||||
Event::WindowEvent { window_id, event: WindowEvent::CursorEntered { device_id } };
|
||||
callback(&self.target, event);
|
||||
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::CursorMoved { device_id, position },
|
||||
event: WindowEvent::PointerEntered {
|
||||
device_id,
|
||||
position,
|
||||
kind: PointerKind::Mouse,
|
||||
},
|
||||
};
|
||||
callback(&self.target, event);
|
||||
}
|
||||
|
|
@ -1193,8 +1216,10 @@ impl EventProcessor {
|
|||
if self.window_exists(window) {
|
||||
let event = Event::WindowEvent {
|
||||
window_id: mkwid(window),
|
||||
event: WindowEvent::CursorLeft {
|
||||
event: WindowEvent::PointerLeft {
|
||||
device_id: Some(mkdid(event.deviceid as xinput::DeviceId)),
|
||||
position: Some(PhysicalPosition::new(event.event_x, event.event_y)),
|
||||
kind: PointerKind::Mouse,
|
||||
},
|
||||
};
|
||||
callback(&self.target, event);
|
||||
|
|
@ -1253,7 +1278,7 @@ impl EventProcessor {
|
|||
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::CursorMoved { device_id, position },
|
||||
event: WindowEvent::PointerMoved { device_id, position, source: PointerSource::Mouse },
|
||||
};
|
||||
callback(&self.target, event);
|
||||
}
|
||||
|
|
@ -1309,7 +1334,7 @@ impl EventProcessor {
|
|||
}
|
||||
}
|
||||
|
||||
fn xinput2_touch<F>(&mut self, xev: &XIDeviceEvent, phase: TouchPhase, mut callback: F)
|
||||
fn xinput2_touch<F>(&mut self, xev: &XIDeviceEvent, phase: i32, mut callback: F)
|
||||
where
|
||||
F: FnMut(&ActiveEventLoop, Event),
|
||||
{
|
||||
|
|
@ -1320,29 +1345,81 @@ impl EventProcessor {
|
|||
if self.window_exists(window) {
|
||||
let window_id = mkwid(window);
|
||||
let id = xev.detail as u32;
|
||||
let location = PhysicalPosition::new(xev.event_x, xev.event_y);
|
||||
let position = PhysicalPosition::new(xev.event_x, xev.event_y);
|
||||
|
||||
// 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) {
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::CursorMoved { device_id: None, position: location.cast() },
|
||||
event: WindowEvent::PointerMoved {
|
||||
device_id: None,
|
||||
position: position.cast(),
|
||||
source: PointerSource::Mouse,
|
||||
},
|
||||
};
|
||||
callback(&self.target, event);
|
||||
}
|
||||
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::Touch(Touch {
|
||||
device_id: Some(mkdid(xev.deviceid as xinput::DeviceId)),
|
||||
phase,
|
||||
location,
|
||||
force: None, // TODO
|
||||
finger_id: mkfid(id),
|
||||
}),
|
||||
};
|
||||
callback(&self.target, event)
|
||||
let device_id = Some(mkdid(xev.deviceid as xinput::DeviceId));
|
||||
let finger_id = mkfid(id);
|
||||
|
||||
match phase {
|
||||
xinput2::XI_TouchBegin => {
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerEntered {
|
||||
device_id,
|
||||
position,
|
||||
kind: PointerKind::Touch(finger_id),
|
||||
},
|
||||
};
|
||||
callback(&self.target, event);
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state: ElementState::Pressed,
|
||||
position,
|
||||
button: ButtonSource::Touch { finger_id, force: None },
|
||||
},
|
||||
};
|
||||
callback(&self.target, event);
|
||||
},
|
||||
xinput2::XI_TouchUpdate => {
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerMoved {
|
||||
device_id,
|
||||
position,
|
||||
source: PointerSource::Touch { finger_id, force: None },
|
||||
},
|
||||
};
|
||||
callback(&self.target, event);
|
||||
},
|
||||
xinput2::XI_TouchEnd => {
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state: ElementState::Released,
|
||||
position,
|
||||
button: ButtonSource::Touch { finger_id, force: None },
|
||||
},
|
||||
};
|
||||
callback(&self.target, event);
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerLeft {
|
||||
device_id,
|
||||
position: Some(position),
|
||||
kind: PointerKind::Touch(finger_id),
|
||||
},
|
||||
};
|
||||
callback(&self.target, event);
|
||||
},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1398,7 +1475,7 @@ impl EventProcessor {
|
|||
if let Some(mouse_delta) = mouse_delta.consume() {
|
||||
let event = Event::DeviceEvent {
|
||||
device_id: did,
|
||||
event: DeviceEvent::MouseMotion { delta: mouse_delta },
|
||||
event: DeviceEvent::PointerMotion { delta: mouse_delta },
|
||||
};
|
||||
callback(&self.target, event);
|
||||
}
|
||||
|
|
@ -1762,15 +1839,15 @@ impl EventProcessor {
|
|||
}
|
||||
}
|
||||
|
||||
fn is_first_touch(first: &mut Option<u32>, num: &mut u32, id: u32, phase: TouchPhase) -> bool {
|
||||
fn is_first_touch(first: &mut Option<u32>, num: &mut u32, id: u32, phase: i32) -> bool {
|
||||
match phase {
|
||||
TouchPhase::Started => {
|
||||
xinput2::XI_TouchBegin => {
|
||||
if *num == 0 {
|
||||
*first = Some(id);
|
||||
}
|
||||
*num += 1;
|
||||
},
|
||||
TouchPhase::Cancelled | TouchPhase::Ended => {
|
||||
xinput2::XI_TouchEnd => {
|
||||
if *first == Some(id) {
|
||||
*first = None;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue