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
|
|
@ -317,48 +317,115 @@ impl EventLoop {
|
|||
InputEvent::MotionEvent(motion_event) => {
|
||||
let window_id = window::WindowId(WindowId);
|
||||
let device_id = Some(event::DeviceId(DeviceId(motion_event.device_id())));
|
||||
let action = motion_event.action();
|
||||
|
||||
let phase = match motion_event.action() {
|
||||
MotionAction::Down | MotionAction::PointerDown => {
|
||||
Some(event::TouchPhase::Started)
|
||||
},
|
||||
MotionAction::Up | MotionAction::PointerUp => Some(event::TouchPhase::Ended),
|
||||
MotionAction::Move => Some(event::TouchPhase::Moved),
|
||||
MotionAction::Cancel => Some(event::TouchPhase::Cancelled),
|
||||
_ => {
|
||||
None // TODO mouse events
|
||||
let pointers: Option<
|
||||
Box<dyn Iterator<Item = android_activity::input::Pointer<'_>>>,
|
||||
> = match action {
|
||||
MotionAction::Down
|
||||
| MotionAction::PointerDown
|
||||
| MotionAction::Up
|
||||
| MotionAction::PointerUp => Some(Box::new(std::iter::once(
|
||||
motion_event.pointer_at_index(motion_event.pointer_index()),
|
||||
))),
|
||||
MotionAction::Move | MotionAction::Cancel => {
|
||||
Some(Box::new(motion_event.pointers()))
|
||||
},
|
||||
// TODO mouse events
|
||||
_ => None,
|
||||
};
|
||||
if let Some(phase) = phase {
|
||||
let pointers: Box<dyn Iterator<Item = android_activity::input::Pointer<'_>>> =
|
||||
match phase {
|
||||
event::TouchPhase::Started | event::TouchPhase::Ended => {
|
||||
Box::new(std::iter::once(
|
||||
motion_event.pointer_at_index(motion_event.pointer_index()),
|
||||
))
|
||||
},
|
||||
event::TouchPhase::Moved | event::TouchPhase::Cancelled => {
|
||||
Box::new(motion_event.pointers())
|
||||
},
|
||||
};
|
||||
|
||||
if let Some(pointers) = pointers {
|
||||
for pointer in pointers {
|
||||
let location =
|
||||
let tool_type = pointer.tool_type();
|
||||
let position =
|
||||
PhysicalPosition { x: pointer.x() as _, y: pointer.y() as _ };
|
||||
trace!(
|
||||
"Input event {device_id:?}, {phase:?}, loc={location:?}, \
|
||||
pointer={pointer:?}"
|
||||
"Input event {device_id:?}, {action:?}, loc={position:?}, \
|
||||
pointer={pointer:?}, tool_type={tool_type:?}"
|
||||
);
|
||||
let finger_id = event::FingerId(FingerId(pointer.pointer_id()));
|
||||
let force = Some(Force::Normalized(pointer.pressure() as f64));
|
||||
|
||||
let event = event::WindowEvent::Touch(event::Touch {
|
||||
device_id,
|
||||
phase,
|
||||
location,
|
||||
finger_id: event::FingerId(FingerId(pointer.pointer_id())),
|
||||
force: Some(Force::Normalized(pointer.pressure() as f64)),
|
||||
});
|
||||
match action {
|
||||
MotionAction::Down | MotionAction::PointerDown => {
|
||||
let event = event::WindowEvent::PointerEntered {
|
||||
device_id,
|
||||
position,
|
||||
kind: match tool_type {
|
||||
android_activity::input::ToolType::Finger => {
|
||||
event::PointerKind::Touch(finger_id)
|
||||
},
|
||||
// TODO mouse events
|
||||
android_activity::input::ToolType::Mouse => continue,
|
||||
_ => event::PointerKind::Unknown,
|
||||
},
|
||||
};
|
||||
app.window_event(&self.window_target, window_id, event);
|
||||
let event = event::WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state: event::ElementState::Pressed,
|
||||
position,
|
||||
button: match tool_type {
|
||||
android_activity::input::ToolType::Finger => {
|
||||
event::ButtonSource::Touch { finger_id, force }
|
||||
},
|
||||
// TODO mouse events
|
||||
android_activity::input::ToolType::Mouse => continue,
|
||||
_ => event::ButtonSource::Unknown(0),
|
||||
},
|
||||
};
|
||||
app.window_event(&self.window_target, window_id, event);
|
||||
},
|
||||
MotionAction::Move => {
|
||||
let event = event::WindowEvent::PointerMoved {
|
||||
device_id,
|
||||
position,
|
||||
source: match tool_type {
|
||||
android_activity::input::ToolType::Finger => {
|
||||
event::PointerSource::Touch { finger_id, force }
|
||||
},
|
||||
// TODO mouse events
|
||||
android_activity::input::ToolType::Mouse => continue,
|
||||
_ => event::PointerSource::Unknown,
|
||||
},
|
||||
};
|
||||
app.window_event(&self.window_target, window_id, event);
|
||||
},
|
||||
MotionAction::Up | MotionAction::PointerUp | MotionAction::Cancel => {
|
||||
if let MotionAction::Up | MotionAction::PointerUp = action {
|
||||
let event = event::WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state: event::ElementState::Released,
|
||||
position,
|
||||
button: match tool_type {
|
||||
android_activity::input::ToolType::Finger => {
|
||||
event::ButtonSource::Touch { finger_id, force }
|
||||
},
|
||||
// TODO mouse events
|
||||
android_activity::input::ToolType::Mouse => continue,
|
||||
_ => event::ButtonSource::Unknown(0),
|
||||
},
|
||||
};
|
||||
app.window_event(&self.window_target, window_id, event);
|
||||
}
|
||||
|
||||
app.window_event(&self.window_target, window_id, event);
|
||||
let event = event::WindowEvent::PointerLeft {
|
||||
device_id,
|
||||
position: Some(position),
|
||||
kind: match tool_type {
|
||||
android_activity::input::ToolType::Finger => {
|
||||
event::PointerKind::Touch(finger_id)
|
||||
},
|
||||
// TODO mouse events
|
||||
android_activity::input::ToolType::Mouse => continue,
|
||||
_ => event::PointerKind::Unknown,
|
||||
},
|
||||
};
|
||||
app.window_event(&self.window_target, window_id, event);
|
||||
},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ fn maybe_dispatch_device_event(app_state: &Rc<AppState>, event: &NSEvent) {
|
|||
|
||||
if delta_x != 0.0 || delta_y != 0.0 {
|
||||
app_state.maybe_queue_with_handler(move |app, event_loop| {
|
||||
app.device_event(event_loop, None, DeviceEvent::MouseMotion {
|
||||
app.device_event(event_loop, None, DeviceEvent::PointerMotion {
|
||||
delta: (delta_x, delta_y),
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@ use super::event::{
|
|||
use super::window::WinitWindow;
|
||||
use crate::dpi::{LogicalPosition, LogicalSize};
|
||||
use crate::event::{
|
||||
DeviceEvent, ElementState, Ime, Modifiers, MouseButton, MouseScrollDelta, TouchPhase,
|
||||
WindowEvent,
|
||||
DeviceEvent, ElementState, Ime, Modifiers, MouseButton, MouseScrollDelta, PointerKind,
|
||||
PointerSource, TouchPhase, WindowEvent,
|
||||
};
|
||||
use crate::keyboard::{Key, KeyCode, KeyLocation, ModifiersState, NamedKey};
|
||||
use crate::platform::macos::OptionAsAlt;
|
||||
|
|
@ -638,19 +638,28 @@ declare_class!(
|
|||
}
|
||||
|
||||
#[method(mouseEntered:)]
|
||||
fn mouse_entered(&self, _event: &NSEvent) {
|
||||
fn mouse_entered(&self, event: &NSEvent) {
|
||||
trace_scope!("mouseEntered:");
|
||||
self.queue_event(WindowEvent::CursorEntered {
|
||||
|
||||
let position = self.mouse_view_point(event).to_physical(self.scale_factor());
|
||||
|
||||
self.queue_event(WindowEvent::PointerEntered {
|
||||
device_id: None,
|
||||
position,
|
||||
kind: PointerKind::Mouse,
|
||||
});
|
||||
}
|
||||
|
||||
#[method(mouseExited:)]
|
||||
fn mouse_exited(&self, _event: &NSEvent) {
|
||||
fn mouse_exited(&self, event: &NSEvent) {
|
||||
trace_scope!("mouseExited:");
|
||||
|
||||
self.queue_event(WindowEvent::CursorLeft {
|
||||
let position = self.mouse_view_point(event).to_physical(self.scale_factor());
|
||||
|
||||
self.queue_event(WindowEvent::PointerLeft {
|
||||
device_id: None,
|
||||
position: Some(position),
|
||||
kind: PointerKind::Mouse,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -1033,16 +1042,21 @@ impl WinitView {
|
|||
}
|
||||
|
||||
fn mouse_click(&self, event: &NSEvent, button_state: ElementState) {
|
||||
let position = self.mouse_view_point(event).to_physical(self.scale_factor());
|
||||
let button = mouse_button(event);
|
||||
|
||||
self.update_modifiers(event, false);
|
||||
|
||||
self.queue_event(WindowEvent::MouseInput { device_id: None, state: button_state, button });
|
||||
self.queue_event(WindowEvent::PointerButton {
|
||||
device_id: None,
|
||||
state: button_state,
|
||||
position,
|
||||
button: button.into(),
|
||||
});
|
||||
}
|
||||
|
||||
fn mouse_motion(&self, event: &NSEvent) {
|
||||
let window_point = unsafe { event.locationInWindow() };
|
||||
let view_point = self.convertPoint_fromView(window_point, None);
|
||||
let view_point = self.mouse_view_point(event);
|
||||
let frame = self.frame();
|
||||
|
||||
if view_point.x.is_sign_negative()
|
||||
|
|
@ -1057,15 +1071,21 @@ impl WinitView {
|
|||
}
|
||||
}
|
||||
|
||||
let view_point = LogicalPosition::new(view_point.x, view_point.y);
|
||||
|
||||
self.update_modifiers(event, false);
|
||||
|
||||
self.queue_event(WindowEvent::CursorMoved {
|
||||
self.queue_event(WindowEvent::PointerMoved {
|
||||
device_id: None,
|
||||
position: view_point.to_physical(self.scale_factor()),
|
||||
source: PointerSource::Mouse,
|
||||
});
|
||||
}
|
||||
|
||||
fn mouse_view_point(&self, event: &NSEvent) -> LogicalPosition<f64> {
|
||||
let window_point = unsafe { event.locationInWindow() };
|
||||
let view_point = self.convertPoint_fromView(window_point, None);
|
||||
|
||||
LogicalPosition::new(view_point.x, view_point.y)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the mouse button from the NSEvent.
|
||||
|
|
|
|||
|
|
@ -17,7 +17,8 @@ use super::window::WinitUIWindow;
|
|||
use super::FingerId;
|
||||
use crate::dpi::PhysicalPosition;
|
||||
use crate::event::{
|
||||
ElementState, Event, FingerId as RootFingerId, Force, KeyEvent, Touch, TouchPhase, WindowEvent,
|
||||
ButtonSource, ElementState, Event, FingerId as RootFingerId, Force, KeyEvent, PointerKind,
|
||||
PointerSource, TouchPhase, WindowEvent,
|
||||
};
|
||||
use crate::keyboard::{Key, KeyCode, KeyLocation, NamedKey, NativeKeyCode, PhysicalKey};
|
||||
use crate::platform_impl::KeyEventExtra;
|
||||
|
|
@ -483,25 +484,18 @@ impl WinitView {
|
|||
for touch in touches {
|
||||
let logical_location = touch.locationInView(None);
|
||||
let touch_type = touch.r#type();
|
||||
let force = if os_supports_force {
|
||||
let force = if let UITouchType::Pencil = touch_type {
|
||||
None
|
||||
} else if os_supports_force {
|
||||
let trait_collection = self.traitCollection();
|
||||
let touch_capability = trait_collection.forceTouchCapability();
|
||||
// Both the OS _and_ the device need to be checked for force touch support.
|
||||
if touch_capability == UIForceTouchCapability::Available
|
||||
|| touch_type == UITouchType::Pencil
|
||||
{
|
||||
if touch_capability == UIForceTouchCapability::Available {
|
||||
let force = touch.force();
|
||||
let max_possible_force = touch.maximumPossibleForce();
|
||||
let altitude_angle: Option<f64> = if touch_type == UITouchType::Pencil {
|
||||
let angle = touch.altitudeAngle();
|
||||
Some(angle as _)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Some(Force::Calibrated {
|
||||
force: force as _,
|
||||
max_possible_force: max_possible_force as _,
|
||||
altitude_angle,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
|
|
@ -511,32 +505,91 @@ impl WinitView {
|
|||
};
|
||||
let touch_id = touch as *const UITouch as usize;
|
||||
let phase = touch.phase();
|
||||
let phase = match phase {
|
||||
UITouchPhase::Began => TouchPhase::Started,
|
||||
UITouchPhase::Moved => TouchPhase::Moved,
|
||||
// 2 is UITouchPhase::Stationary and is not expected here
|
||||
UITouchPhase::Ended => TouchPhase::Ended,
|
||||
UITouchPhase::Cancelled => TouchPhase::Cancelled,
|
||||
_ => panic!("unexpected touch phase: {phase:?}"),
|
||||
};
|
||||
|
||||
let physical_location = {
|
||||
let position = {
|
||||
let scale_factor = self.contentScaleFactor();
|
||||
PhysicalPosition::from_logical::<(f64, f64), f64>(
|
||||
(logical_location.x as _, logical_location.y as _),
|
||||
scale_factor as f64,
|
||||
)
|
||||
};
|
||||
touch_events.push(EventWrapper::StaticEvent(Event::WindowEvent {
|
||||
window_id: RootWindowId(window.id()),
|
||||
event: WindowEvent::Touch(Touch {
|
||||
device_id: None,
|
||||
finger_id: RootFingerId(FingerId(touch_id)),
|
||||
location: physical_location,
|
||||
force,
|
||||
phase,
|
||||
}),
|
||||
}));
|
||||
let window_id = RootWindowId(window.id());
|
||||
let finger_id = RootFingerId(FingerId(touch_id));
|
||||
|
||||
match phase {
|
||||
UITouchPhase::Began => {
|
||||
touch_events.push(EventWrapper::StaticEvent(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerEntered {
|
||||
device_id: None,
|
||||
position,
|
||||
kind: if let UITouchType::Pencil = touch_type {
|
||||
PointerKind::Unknown
|
||||
} else {
|
||||
PointerKind::Touch(finger_id)
|
||||
},
|
||||
},
|
||||
}));
|
||||
touch_events.push(EventWrapper::StaticEvent(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerButton {
|
||||
device_id: None,
|
||||
state: ElementState::Pressed,
|
||||
position,
|
||||
button: if let UITouchType::Pencil = touch_type {
|
||||
ButtonSource::Unknown(0)
|
||||
} else {
|
||||
ButtonSource::Touch { finger_id, force }
|
||||
},
|
||||
},
|
||||
}));
|
||||
},
|
||||
UITouchPhase::Moved => {
|
||||
touch_events.push(EventWrapper::StaticEvent(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerMoved {
|
||||
device_id: None,
|
||||
position,
|
||||
source: if let UITouchType::Pencil = touch_type {
|
||||
PointerSource::Unknown
|
||||
} else {
|
||||
PointerSource::Touch { finger_id, force }
|
||||
},
|
||||
},
|
||||
}));
|
||||
},
|
||||
// 2 is UITouchPhase::Stationary and is not expected here
|
||||
UITouchPhase::Ended | UITouchPhase::Cancelled => {
|
||||
if let UITouchPhase::Ended = phase {
|
||||
touch_events.push(EventWrapper::StaticEvent(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerButton {
|
||||
device_id: None,
|
||||
state: ElementState::Released,
|
||||
position,
|
||||
button: if let UITouchType::Pencil = touch_type {
|
||||
ButtonSource::Unknown(0)
|
||||
} else {
|
||||
ButtonSource::Touch { finger_id, force }
|
||||
},
|
||||
},
|
||||
}));
|
||||
}
|
||||
|
||||
touch_events.push(EventWrapper::StaticEvent(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerLeft {
|
||||
device_id: None,
|
||||
position: Some(position),
|
||||
kind: if let UITouchType::Pencil = touch_type {
|
||||
PointerKind::Unknown
|
||||
} else {
|
||||
PointerKind::Touch(finger_id)
|
||||
},
|
||||
},
|
||||
}));
|
||||
},
|
||||
_ => panic!("unexpected touch phase: {phase:?}"),
|
||||
}
|
||||
}
|
||||
let mtm = MainThreadMarker::new().unwrap();
|
||||
app_state::handle_nonuser_events(mtm, touch_events);
|
||||
|
|
|
|||
|
|
@ -638,7 +638,7 @@ pub fn keysym_to_key(keysym: u32) -> Key {
|
|||
// keysyms::ISO_Release_Margin_Left => NamedKey::IsoReleaseMarginLeft,
|
||||
// keysyms::ISO_Release_Margin_Right => NamedKey::IsoReleaseMarginRight,
|
||||
// keysyms::ISO_Release_Both_Margins => NamedKey::IsoReleaseBothMargins,
|
||||
// keysyms::ISO_Fast_Cursor_Left => NamedKey::IsoFastCursorLeft,
|
||||
// keysyms::ISO_Fast_Cursor_Left => NamedKey::IsoFastPointerLeft,
|
||||
// keysyms::ISO_Fast_Cursor_Right => NamedKey::IsoFastCursorRight,
|
||||
// keysyms::ISO_Fast_Cursor_Up => NamedKey::IsoFastCursorUp,
|
||||
// keysyms::ISO_Fast_Cursor_Down => NamedKey::IsoFastCursorDown,
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ use sctk::seat::pointer::{
|
|||
use sctk::seat::SeatState;
|
||||
|
||||
use crate::dpi::{LogicalPosition, PhysicalPosition};
|
||||
use crate::event::{ElementState, MouseButton, MouseScrollDelta, TouchPhase, WindowEvent};
|
||||
use crate::event::{ElementState, MouseButton, MouseScrollDelta, PointerSource, PointerKind, TouchPhase, WindowEvent};
|
||||
|
||||
use crate::platform_impl::wayland::state::WinitState;
|
||||
use crate::platform_impl::wayland::{self, WindowId};
|
||||
|
|
@ -123,7 +123,11 @@ impl PointerHandler for WinitState {
|
|||
// Regular events on the main surface.
|
||||
PointerEventKind::Enter { .. } => {
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::CursorEntered { device_id: None },
|
||||
WindowEvent::PointerEntered {
|
||||
device_id: None,
|
||||
position,
|
||||
kind: PointerKind::Mouse,
|
||||
},
|
||||
window_id,
|
||||
);
|
||||
|
||||
|
|
@ -131,11 +135,6 @@ impl PointerHandler for WinitState {
|
|||
|
||||
// Set the currently focused surface.
|
||||
pointer.winit_data().inner.lock().unwrap().surface = Some(window_id);
|
||||
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::CursorMoved { device_id: None, position },
|
||||
window_id,
|
||||
);
|
||||
},
|
||||
PointerEventKind::Leave { .. } => {
|
||||
window.pointer_left(Arc::downgrade(themed_pointer));
|
||||
|
|
@ -143,12 +142,22 @@ impl PointerHandler for WinitState {
|
|||
// Remove the active surface.
|
||||
pointer.winit_data().inner.lock().unwrap().surface = None;
|
||||
|
||||
self.events_sink
|
||||
.push_window_event(WindowEvent::CursorLeft { device_id: None }, window_id);
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::PointerLeft {
|
||||
device_id: None,
|
||||
position: Some(position),
|
||||
kind: PointerKind::Mouse,
|
||||
},
|
||||
window_id,
|
||||
);
|
||||
},
|
||||
PointerEventKind::Motion { .. } => {
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::CursorMoved { device_id: None, position },
|
||||
WindowEvent::PointerMoved {
|
||||
device_id: None,
|
||||
position,
|
||||
source: PointerSource::Mouse,
|
||||
},
|
||||
window_id,
|
||||
);
|
||||
},
|
||||
|
|
@ -164,7 +173,12 @@ impl PointerHandler for WinitState {
|
|||
ElementState::Released
|
||||
};
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::MouseInput { device_id: None, state, button },
|
||||
WindowEvent::PointerButton {
|
||||
device_id: None,
|
||||
state,
|
||||
position,
|
||||
button: button.into(),
|
||||
},
|
||||
window_id,
|
||||
);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ impl Dispatch<ZwpRelativePointerV1, GlobalData, WinitState> for RelativePointerS
|
|||
};
|
||||
state
|
||||
.events_sink
|
||||
.push_device_event(DeviceEvent::MouseMotion { delta: (dx_unaccel, dy_unaccel) });
|
||||
.push_device_event(DeviceEvent::PointerMotion { delta: (dx_unaccel, dy_unaccel) });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use sctk::seat::touch::{TouchData, TouchHandler};
|
|||
use tracing::warn;
|
||||
|
||||
use crate::dpi::LogicalPosition;
|
||||
use crate::event::{Touch, TouchPhase, WindowEvent};
|
||||
use crate::event::{ButtonSource, ElementState, PointerKind, PointerSource, WindowEvent};
|
||||
use crate::platform_impl::wayland::state::WinitState;
|
||||
use crate::platform_impl::wayland::{self, FingerId};
|
||||
|
||||
|
|
@ -42,16 +42,25 @@ impl TouchHandler for WinitState {
|
|||
let location = LogicalPosition::<f64>::from(position);
|
||||
seat_state.touch_map.insert(id, TouchPoint { surface, location });
|
||||
|
||||
let position = location.to_physical(scale_factor);
|
||||
let finger_id =
|
||||
crate::event::FingerId(crate::platform_impl::FingerId::Wayland(FingerId(id)));
|
||||
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::Touch(Touch {
|
||||
WindowEvent::PointerEntered {
|
||||
device_id: None,
|
||||
phase: TouchPhase::Started,
|
||||
location: location.to_physical(scale_factor),
|
||||
force: None,
|
||||
finger_id: crate::event::FingerId(crate::platform_impl::FingerId::Wayland(
|
||||
FingerId(id),
|
||||
)),
|
||||
}),
|
||||
position,
|
||||
kind: PointerKind::Touch(finger_id),
|
||||
},
|
||||
window_id,
|
||||
);
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::PointerButton {
|
||||
device_id: None,
|
||||
state: ElementState::Pressed,
|
||||
position,
|
||||
button: ButtonSource::Touch { finger_id, force: None },
|
||||
},
|
||||
window_id,
|
||||
);
|
||||
}
|
||||
|
|
@ -85,16 +94,25 @@ impl TouchHandler for WinitState {
|
|||
None => return,
|
||||
};
|
||||
|
||||
let position = touch_point.location.to_physical(scale_factor);
|
||||
let finger_id =
|
||||
crate::event::FingerId(crate::platform_impl::FingerId::Wayland(FingerId(id)));
|
||||
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::Touch(Touch {
|
||||
WindowEvent::PointerButton {
|
||||
device_id: None,
|
||||
phase: TouchPhase::Ended,
|
||||
location: touch_point.location.to_physical(scale_factor),
|
||||
force: None,
|
||||
finger_id: crate::event::FingerId(crate::platform_impl::FingerId::Wayland(
|
||||
FingerId(id),
|
||||
)),
|
||||
}),
|
||||
state: ElementState::Released,
|
||||
position,
|
||||
button: ButtonSource::Touch { finger_id, force: None },
|
||||
},
|
||||
window_id,
|
||||
);
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::PointerLeft {
|
||||
device_id: None,
|
||||
position: Some(position),
|
||||
kind: PointerKind::Touch(finger_id),
|
||||
},
|
||||
window_id,
|
||||
);
|
||||
}
|
||||
|
|
@ -131,15 +149,16 @@ impl TouchHandler for WinitState {
|
|||
touch_point.location = LogicalPosition::<f64>::from(position);
|
||||
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::Touch(Touch {
|
||||
WindowEvent::PointerMoved {
|
||||
device_id: None,
|
||||
phase: TouchPhase::Moved,
|
||||
location: touch_point.location.to_physical(scale_factor),
|
||||
force: None,
|
||||
finger_id: crate::event::FingerId(crate::platform_impl::FingerId::Wayland(
|
||||
FingerId(id),
|
||||
)),
|
||||
}),
|
||||
position: touch_point.location.to_physical(scale_factor),
|
||||
source: PointerSource::Touch {
|
||||
finger_id: crate::event::FingerId(crate::platform_impl::FingerId::Wayland(
|
||||
FingerId(id),
|
||||
)),
|
||||
force: None,
|
||||
},
|
||||
},
|
||||
window_id,
|
||||
);
|
||||
}
|
||||
|
|
@ -160,18 +179,16 @@ impl TouchHandler for WinitState {
|
|||
None => return,
|
||||
};
|
||||
|
||||
let location = touch_point.location.to_physical(scale_factor);
|
||||
let position = touch_point.location.to_physical(scale_factor);
|
||||
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::Touch(Touch {
|
||||
WindowEvent::PointerLeft {
|
||||
device_id: None,
|
||||
phase: TouchPhase::Cancelled,
|
||||
location,
|
||||
force: None,
|
||||
finger_id: crate::event::FingerId(crate::platform_impl::FingerId::Wayland(
|
||||
FingerId(id),
|
||||
position: Some(position),
|
||||
kind: PointerKind::Touch(crate::event::FingerId(
|
||||
crate::platform_impl::FingerId::Wayland(FingerId(id)),
|
||||
)),
|
||||
}),
|
||||
},
|
||||
window_id,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -407,11 +407,15 @@ impl EventLoop {
|
|||
app.window_event(
|
||||
window_target,
|
||||
RootWindowId(window_id),
|
||||
event::WindowEvent::CursorMoved { device_id: None, position: (x, y).into() },
|
||||
event::WindowEvent::PointerMoved {
|
||||
device_id: None,
|
||||
position: (x, y).into(),
|
||||
source: event::PointerSource::Mouse,
|
||||
},
|
||||
);
|
||||
},
|
||||
EventOption::MouseRelative(MouseRelativeEvent { dx, dy }) => {
|
||||
app.device_event(window_target, None, event::DeviceEvent::MouseMotion {
|
||||
app.device_event(window_target, None, event::DeviceEvent::PointerMotion {
|
||||
delta: (dx as f64, dy as f64),
|
||||
});
|
||||
},
|
||||
|
|
@ -420,7 +424,12 @@ impl EventLoop {
|
|||
app.window_event(
|
||||
window_target,
|
||||
RootWindowId(window_id),
|
||||
event::WindowEvent::MouseInput { device_id: None, state, button },
|
||||
event::WindowEvent::PointerButton {
|
||||
device_id: None,
|
||||
state,
|
||||
position: dpi::PhysicalPosition::default(),
|
||||
button: button.into(),
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
|
|
@ -469,9 +478,17 @@ impl EventLoop {
|
|||
// TODO: Screen, Clipboard, Drop
|
||||
EventOption::Hover(HoverEvent { entered }) => {
|
||||
let event = if entered {
|
||||
event::WindowEvent::CursorEntered { device_id: None }
|
||||
event::WindowEvent::PointerEntered {
|
||||
device_id: None,
|
||||
position: dpi::PhysicalPosition::default(),
|
||||
kind: event::PointerKind::Mouse,
|
||||
}
|
||||
} else {
|
||||
event::WindowEvent::CursorLeft { device_id: None }
|
||||
event::WindowEvent::PointerLeft {
|
||||
device_id: None,
|
||||
position: None,
|
||||
kind: event::PointerKind::Mouse,
|
||||
}
|
||||
};
|
||||
|
||||
app.window_event(window_target, RootWindowId(window_id), event);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
#[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
|
||||
pub struct DeviceId(u32);
|
||||
use crate::event::FingerId as RootFingerId;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct DeviceId(pub(crate) u32);
|
||||
|
||||
impl DeviceId {
|
||||
pub fn new(pointer_id: i32) -> Option<Self> {
|
||||
|
|
@ -34,3 +36,9 @@ impl FingerId {
|
|||
self.primary
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FingerId> for RootFingerId {
|
||||
fn from(id: FingerId) -> Self {
|
||||
Self(id)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -297,7 +297,7 @@ impl Shared {
|
|||
|
||||
runner.send_event(Event::DeviceEvent {
|
||||
device_id,
|
||||
event: DeviceEvent::Button { button: button.to_id(), state },
|
||||
event: DeviceEvent::Button { button: button.to_id().into(), state },
|
||||
});
|
||||
|
||||
return;
|
||||
|
|
@ -310,7 +310,7 @@ impl Shared {
|
|||
|
||||
Event::DeviceEvent {
|
||||
device_id,
|
||||
event: DeviceEvent::MouseMotion { delta: (delta.x, delta.y) },
|
||||
event: DeviceEvent::PointerMotion { delta: (delta.x, delta.y) },
|
||||
}
|
||||
}));
|
||||
}),
|
||||
|
|
@ -346,7 +346,7 @@ impl Shared {
|
|||
runner.send_event(Event::DeviceEvent {
|
||||
device_id: DeviceId::new(event.pointer_id()).map(RootDeviceId),
|
||||
event: DeviceEvent::Button {
|
||||
button: button.to_id(),
|
||||
button: button.to_id().into(),
|
||||
state: ElementState::Pressed,
|
||||
},
|
||||
});
|
||||
|
|
@ -365,7 +365,7 @@ impl Shared {
|
|||
runner.send_event(Event::DeviceEvent {
|
||||
device_id: DeviceId::new(event.pointer_id()).map(RootDeviceId),
|
||||
event: DeviceEvent::Button {
|
||||
button: button.to_id(),
|
||||
button: button.to_id().into(),
|
||||
state: ElementState::Released,
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -12,8 +12,7 @@ use super::window::WindowId;
|
|||
use super::{backend, runner, EventLoopProxy};
|
||||
use crate::error::{NotSupportedError, RequestError};
|
||||
use crate::event::{
|
||||
DeviceId as RootDeviceId, ElementState, Event, FingerId as RootFingerId, KeyEvent, Touch,
|
||||
TouchPhase, WindowEvent,
|
||||
DeviceId as RootDeviceId, ElementState, Event, KeyEvent, TouchPhase, WindowEvent,
|
||||
};
|
||||
use crate::event_loop::{
|
||||
ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents,
|
||||
|
|
@ -200,12 +199,12 @@ impl ActiveEventLoop {
|
|||
);
|
||||
|
||||
let has_focus = canvas.has_focus.clone();
|
||||
canvas.on_cursor_leave({
|
||||
canvas.on_pointer_leave({
|
||||
let runner = self.runner.clone();
|
||||
let has_focus = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, pointer_id| {
|
||||
move |active_modifiers, device_id, position, kind| {
|
||||
let focus = (has_focus.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
|
|
@ -214,23 +213,23 @@ impl ActiveEventLoop {
|
|||
}
|
||||
});
|
||||
|
||||
let pointer = pointer_id.map(|device_id| Event::WindowEvent {
|
||||
runner.send_events(focus.into_iter().chain(iter::once(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::CursorLeft { device_id: device_id.map(RootDeviceId) },
|
||||
});
|
||||
|
||||
if focus.is_some() || pointer.is_some() {
|
||||
runner.send_events(focus.into_iter().chain(pointer))
|
||||
}
|
||||
event: WindowEvent::PointerLeft {
|
||||
device_id: device_id.map(RootDeviceId),
|
||||
position: Some(position),
|
||||
kind,
|
||||
},
|
||||
})))
|
||||
}
|
||||
});
|
||||
|
||||
canvas.on_cursor_enter({
|
||||
canvas.on_pointer_enter({
|
||||
let runner = self.runner.clone();
|
||||
let has_focus = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, pointer_id| {
|
||||
move |active_modifiers, device_id, position, kind| {
|
||||
let focus = (has_focus.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
|
|
@ -239,41 +238,41 @@ impl ActiveEventLoop {
|
|||
}
|
||||
});
|
||||
|
||||
let pointer = pointer_id.map(|device_id| Event::WindowEvent {
|
||||
runner.send_events(focus.into_iter().chain(iter::once(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::CursorEntered { device_id: device_id.map(RootDeviceId) },
|
||||
});
|
||||
|
||||
if focus.is_some() || pointer.is_some() {
|
||||
runner.send_events(focus.into_iter().chain(pointer))
|
||||
}
|
||||
event: WindowEvent::PointerEntered {
|
||||
device_id: device_id.map(RootDeviceId),
|
||||
position,
|
||||
kind,
|
||||
},
|
||||
})))
|
||||
}
|
||||
});
|
||||
|
||||
canvas.on_cursor_move(
|
||||
canvas.on_pointer_move(
|
||||
{
|
||||
let runner = self.runner.clone();
|
||||
let has_focus = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, pointer_id, events| {
|
||||
let modifiers =
|
||||
(has_focus.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
runner.send_events(modifiers.into_iter().chain(events.flat_map(|position| {
|
||||
move |pointer_id, events| {
|
||||
runner.send_events(events.flat_map(|(active_modifiers, position, source)| {
|
||||
let device_id = pointer_id.map(RootDeviceId);
|
||||
|
||||
iter::once(Event::WindowEvent {
|
||||
let modifiers = (has_focus.get() && modifiers.get() != active_modifiers)
|
||||
.then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
modifiers.into_iter().chain(iter::once(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::CursorMoved { device_id, position },
|
||||
})
|
||||
})));
|
||||
event: WindowEvent::PointerMoved { device_id, position, source },
|
||||
}))
|
||||
}));
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -281,40 +280,7 @@ impl ActiveEventLoop {
|
|||
let has_focus = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, device_id, finger_id, events| {
|
||||
let modifiers =
|
||||
(has_focus.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
runner.send_events(modifiers.into_iter().chain(events.map(
|
||||
|(location, force)| Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::Touch(Touch {
|
||||
finger_id: RootFingerId(finger_id),
|
||||
device_id: device_id.map(RootDeviceId),
|
||||
phase: TouchPhase::Moved,
|
||||
force: Some(force),
|
||||
location,
|
||||
}),
|
||||
},
|
||||
)));
|
||||
}
|
||||
},
|
||||
{
|
||||
let runner = self.runner.clone();
|
||||
let has_focus = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers,
|
||||
device_id,
|
||||
position: crate::dpi::PhysicalPosition<f64>,
|
||||
buttons,
|
||||
button| {
|
||||
move |active_modifiers, device_id, position, state, button| {
|
||||
let modifiers =
|
||||
(has_focus.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
|
|
@ -326,36 +292,48 @@ impl ActiveEventLoop {
|
|||
|
||||
let device_id = device_id.map(RootDeviceId);
|
||||
|
||||
let state = if buttons.contains(button.into()) {
|
||||
ElementState::Pressed
|
||||
} else {
|
||||
ElementState::Released
|
||||
};
|
||||
|
||||
// A chorded button event may come in without any prior CursorMoved events,
|
||||
// therefore we should send a CursorMoved event to make sure that the
|
||||
// user code has the correct cursor position.
|
||||
runner.send_events(modifiers.into_iter().chain([
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::CursorMoved { device_id, position },
|
||||
},
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::MouseInput { device_id, state, button },
|
||||
},
|
||||
]));
|
||||
runner.send_events(modifiers.into_iter().chain([Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::PointerButton { device_id, state, position, button },
|
||||
}]));
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
canvas.on_mouse_press(
|
||||
{
|
||||
let runner = self.runner.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
canvas.on_pointer_press({
|
||||
let runner = self.runner.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, pointer_id, position, button| {
|
||||
let modifiers = (modifiers.get() != active_modifiers).then(|| {
|
||||
move |active_modifiers, pointer_id, position, button| {
|
||||
let modifiers = (modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
let device_id = pointer_id.map(RootDeviceId);
|
||||
runner.send_events(modifiers.into_iter().chain(iter::once(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state: ElementState::Pressed,
|
||||
position,
|
||||
button,
|
||||
},
|
||||
})));
|
||||
}
|
||||
});
|
||||
|
||||
canvas.on_pointer_release({
|
||||
let runner = self.runner.clone();
|
||||
let has_focus = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, pointer_id, position, button| {
|
||||
let modifiers =
|
||||
(has_focus.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
|
|
@ -363,123 +341,19 @@ impl ActiveEventLoop {
|
|||
}
|
||||
});
|
||||
|
||||
let device_id = pointer_id.map(RootDeviceId);
|
||||
let device_id = pointer_id.map(RootDeviceId);
|
||||
|
||||
// A mouse down event may come in without any prior CursorMoved events,
|
||||
// therefore we should send a CursorMoved event to make sure that the
|
||||
// user code has the correct cursor position.
|
||||
runner.send_events(modifiers.into_iter().chain([
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::CursorMoved { device_id, position },
|
||||
},
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::MouseInput {
|
||||
device_id,
|
||||
state: ElementState::Pressed,
|
||||
button,
|
||||
},
|
||||
},
|
||||
]));
|
||||
}
|
||||
},
|
||||
{
|
||||
let runner = self.runner.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, device_id, finger_id, location, force| {
|
||||
let modifiers = (modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
runner.send_events(modifiers.into_iter().chain(iter::once(
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::Touch(Touch {
|
||||
finger_id: RootFingerId(finger_id),
|
||||
device_id: device_id.map(RootDeviceId),
|
||||
phase: TouchPhase::Started,
|
||||
force: Some(force),
|
||||
location,
|
||||
}),
|
||||
},
|
||||
)))
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
canvas.on_mouse_release(
|
||||
{
|
||||
let runner = self.runner.clone();
|
||||
let has_focus = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, pointer_id, position, button| {
|
||||
let modifiers =
|
||||
(has_focus.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
let device_id = pointer_id.map(RootDeviceId);
|
||||
|
||||
// A mouse up event may come in without any prior CursorMoved events,
|
||||
// therefore we should send a CursorMoved event to make sure that the
|
||||
// user code has the correct cursor position.
|
||||
runner.send_events(modifiers.into_iter().chain([
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::CursorMoved { device_id, position },
|
||||
},
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::MouseInput {
|
||||
device_id,
|
||||
state: ElementState::Released,
|
||||
button,
|
||||
},
|
||||
},
|
||||
]));
|
||||
}
|
||||
},
|
||||
{
|
||||
let runner_touch = self.runner.clone();
|
||||
let has_focus = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, device_id, finger_id, location, force| {
|
||||
let modifiers =
|
||||
(has_focus.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
runner_touch.send_events(modifiers.into_iter().chain(iter::once(
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::Touch(Touch {
|
||||
finger_id: RootFingerId(finger_id),
|
||||
device_id: device_id.map(RootDeviceId),
|
||||
phase: TouchPhase::Ended,
|
||||
force: Some(force),
|
||||
location,
|
||||
}),
|
||||
},
|
||||
)));
|
||||
}
|
||||
},
|
||||
);
|
||||
runner.send_events(modifiers.into_iter().chain(iter::once(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state: ElementState::Released,
|
||||
position,
|
||||
button,
|
||||
},
|
||||
})));
|
||||
}
|
||||
});
|
||||
|
||||
let runner = self.runner.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
|
@ -505,20 +379,6 @@ impl ActiveEventLoop {
|
|||
)));
|
||||
});
|
||||
|
||||
let runner = self.runner.clone();
|
||||
canvas.on_touch_cancel(move |device_id, finger_id, location, force| {
|
||||
runner.send_event(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::Touch(Touch {
|
||||
finger_id: RootFingerId(finger_id),
|
||||
device_id: device_id.map(RootDeviceId),
|
||||
phase: TouchPhase::Cancelled,
|
||||
force: Some(force),
|
||||
location,
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
let runner = self.runner.clone();
|
||||
canvas.on_dark_mode(move |is_dark_mode| {
|
||||
let theme = if is_dark_mode { Theme::Dark } else { Theme::Light };
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use web_sys::{
|
|||
};
|
||||
|
||||
use super::super::cursor::CursorHandler;
|
||||
use super::super::event::{DeviceId, FingerId};
|
||||
use super::super::event::DeviceId;
|
||||
use super::super::main_thread::MainThreadMarker;
|
||||
use super::super::WindowId;
|
||||
use super::animation_frame::AnimationFrameHandler;
|
||||
|
|
@ -20,10 +20,12 @@ use super::event_handle::EventListenerHandle;
|
|||
use super::intersection_handle::IntersectionObserverHandle;
|
||||
use super::media_query_handle::MediaQueryListHandle;
|
||||
use super::pointer::PointerHandler;
|
||||
use super::{event, fullscreen, ButtonsState, ResizeScaleHandle};
|
||||
use super::{event, fullscreen, ResizeScaleHandle};
|
||||
use crate::dpi::{LogicalPosition, PhysicalPosition, PhysicalSize};
|
||||
use crate::error::RequestError;
|
||||
use crate::event::{Force, MouseButton, MouseScrollDelta, SurfaceSizeWriter};
|
||||
use crate::event::{
|
||||
ButtonSource, ElementState, MouseScrollDelta, PointerKind, PointerSource, SurfaceSizeWriter,
|
||||
};
|
||||
use crate::keyboard::{Key, KeyLocation, ModifiersState, PhysicalKey};
|
||||
use crate::platform_impl::Fullscreen;
|
||||
use crate::window::{WindowAttributes, WindowId as RootWindowId};
|
||||
|
|
@ -328,83 +330,62 @@ impl Canvas {
|
|||
}));
|
||||
}
|
||||
|
||||
pub fn on_cursor_leave<F>(&self, handler: F)
|
||||
pub fn on_pointer_leave<F>(&self, handler: F)
|
||||
where
|
||||
F: 'static + FnMut(ModifiersState, Option<Option<DeviceId>>),
|
||||
F: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, PointerKind),
|
||||
{
|
||||
self.handlers.borrow_mut().pointer_handler.on_cursor_leave(&self.common, handler)
|
||||
self.handlers.borrow_mut().pointer_handler.on_pointer_leave(&self.common, handler)
|
||||
}
|
||||
|
||||
pub fn on_cursor_enter<F>(&self, handler: F)
|
||||
pub fn on_pointer_enter<F>(&self, handler: F)
|
||||
where
|
||||
F: 'static + FnMut(ModifiersState, Option<Option<DeviceId>>),
|
||||
F: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, PointerKind),
|
||||
{
|
||||
self.handlers.borrow_mut().pointer_handler.on_cursor_enter(&self.common, handler)
|
||||
self.handlers.borrow_mut().pointer_handler.on_pointer_enter(&self.common, handler)
|
||||
}
|
||||
|
||||
pub fn on_mouse_release<M, T>(&self, mouse_handler: M, touch_handler: T)
|
||||
pub fn on_pointer_release<C>(&self, handler: C)
|
||||
where
|
||||
M: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, MouseButton),
|
||||
T: 'static
|
||||
+ FnMut(ModifiersState, Option<DeviceId>, FingerId, PhysicalPosition<f64>, Force),
|
||||
C: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, ButtonSource),
|
||||
{
|
||||
self.handlers.borrow_mut().pointer_handler.on_mouse_release(
|
||||
self.handlers.borrow_mut().pointer_handler.on_pointer_release(&self.common, handler)
|
||||
}
|
||||
|
||||
pub fn on_pointer_press<C>(&self, handler: C)
|
||||
where
|
||||
C: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, ButtonSource),
|
||||
{
|
||||
self.handlers.borrow_mut().pointer_handler.on_pointer_press(
|
||||
&self.common,
|
||||
mouse_handler,
|
||||
touch_handler,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn on_mouse_press<M, T>(&self, mouse_handler: M, touch_handler: T)
|
||||
where
|
||||
M: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, MouseButton),
|
||||
T: 'static
|
||||
+ FnMut(ModifiersState, Option<DeviceId>, FingerId, PhysicalPosition<f64>, Force),
|
||||
{
|
||||
self.handlers.borrow_mut().pointer_handler.on_mouse_press(
|
||||
&self.common,
|
||||
mouse_handler,
|
||||
touch_handler,
|
||||
handler,
|
||||
Rc::clone(&self.prevent_default),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn on_cursor_move<M, T, B>(&self, mouse_handler: M, touch_handler: T, button_handler: B)
|
||||
pub fn on_pointer_move<C, B>(&self, cursor_handler: C, button_handler: B)
|
||||
where
|
||||
M: 'static
|
||||
+ FnMut(ModifiersState, Option<DeviceId>, &mut dyn Iterator<Item = PhysicalPosition<f64>>),
|
||||
T: 'static
|
||||
C: 'static
|
||||
+ FnMut(
|
||||
ModifiersState,
|
||||
Option<DeviceId>,
|
||||
FingerId,
|
||||
&mut dyn Iterator<Item = (PhysicalPosition<f64>, Force)>,
|
||||
&mut dyn Iterator<Item = (ModifiersState, PhysicalPosition<f64>, PointerSource)>,
|
||||
),
|
||||
B: 'static
|
||||
+ FnMut(
|
||||
ModifiersState,
|
||||
Option<DeviceId>,
|
||||
PhysicalPosition<f64>,
|
||||
ButtonsState,
|
||||
MouseButton,
|
||||
ElementState,
|
||||
ButtonSource,
|
||||
),
|
||||
{
|
||||
self.handlers.borrow_mut().pointer_handler.on_cursor_move(
|
||||
self.handlers.borrow_mut().pointer_handler.on_pointer_move(
|
||||
&self.common,
|
||||
mouse_handler,
|
||||
touch_handler,
|
||||
cursor_handler,
|
||||
button_handler,
|
||||
Rc::clone(&self.prevent_default),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn on_touch_cancel<F>(&self, handler: F)
|
||||
where
|
||||
F: 'static + FnMut(Option<DeviceId>, FingerId, PhysicalPosition<f64>, Force),
|
||||
{
|
||||
self.handlers.borrow_mut().pointer_handler.on_touch_cancel(&self.common, handler)
|
||||
}
|
||||
|
||||
pub fn on_mouse_wheel<F>(&self, mut handler: F)
|
||||
where
|
||||
F: 'static + FnMut(MouseScrollDelta, ModifiersState),
|
||||
|
|
|
|||
|
|
@ -6,8 +6,9 @@ use wasm_bindgen::prelude::wasm_bindgen;
|
|||
use wasm_bindgen::{JsCast, JsValue};
|
||||
use web_sys::{KeyboardEvent, MouseEvent, Navigator, PointerEvent, WheelEvent};
|
||||
|
||||
use super::super::FingerId;
|
||||
use super::Engine;
|
||||
use crate::event::{MouseButton, MouseScrollDelta};
|
||||
use crate::event::{MouseButton, MouseScrollDelta, PointerKind};
|
||||
use crate::keyboard::{Key, KeyLocation, ModifiersState, NamedKey, PhysicalKey};
|
||||
|
||||
bitflags::bitflags! {
|
||||
|
|
@ -68,14 +69,14 @@ pub fn mouse_button(event: &MouseEvent) -> Option<MouseButton> {
|
|||
}
|
||||
|
||||
impl MouseButton {
|
||||
pub fn to_id(self) -> u32 {
|
||||
pub fn to_id(self) -> u16 {
|
||||
match self {
|
||||
MouseButton::Left => 0,
|
||||
MouseButton::Right => 1,
|
||||
MouseButton::Middle => 2,
|
||||
MouseButton::Back => 3,
|
||||
MouseButton::Forward => 4,
|
||||
MouseButton::Other(value) => value.into(),
|
||||
MouseButton::Other(value) => value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -160,6 +161,14 @@ pub fn mouse_scroll_delta(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn pointer_type(event: &PointerEvent, pointer_id: i32) -> PointerKind {
|
||||
match event.pointer_type().as_str() {
|
||||
"mouse" => PointerKind::Mouse,
|
||||
"touch" => PointerKind::Touch(FingerId::new(pointer_id, event.is_primary()).into()),
|
||||
_ => PointerKind::Unknown,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn key_code(event: &KeyboardEvent) -> PhysicalKey {
|
||||
let code = event.code();
|
||||
PhysicalKey::from_key_code_attribute_value(&code)
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ use wasm_bindgen::JsCast;
|
|||
use web_sys::{Document, HtmlCanvasElement, Navigator, PageTransitionEvent, VisibilityState};
|
||||
|
||||
pub use self::canvas::{Canvas, Style};
|
||||
pub use self::event::ButtonsState;
|
||||
pub use self::event_handle::EventListenerHandle;
|
||||
pub use self::resize_scaling::ResizeScaleHandle;
|
||||
pub use self::schedule::Schedule;
|
||||
|
|
|
|||
|
|
@ -1,15 +1,14 @@
|
|||
use std::cell::Cell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use event::ButtonsState;
|
||||
use web_sys::PointerEvent;
|
||||
|
||||
use super::super::event::{DeviceId, FingerId};
|
||||
use super::super::event::DeviceId;
|
||||
use super::canvas::Common;
|
||||
use super::event;
|
||||
use super::event_handle::EventListenerHandle;
|
||||
use crate::dpi::PhysicalPosition;
|
||||
use crate::event::{Force, MouseButton};
|
||||
use crate::event::{ButtonSource, ElementState, Force, PointerKind, PointerSource};
|
||||
use crate::keyboard::ModifiersState;
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
|
@ -34,88 +33,78 @@ impl PointerHandler {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn on_cursor_leave<F>(&mut self, canvas_common: &Common, mut handler: F)
|
||||
pub fn on_pointer_leave<F>(&mut self, canvas_common: &Common, mut handler: F)
|
||||
where
|
||||
F: 'static + FnMut(ModifiersState, Option<Option<DeviceId>>),
|
||||
F: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, PointerKind),
|
||||
{
|
||||
let window = canvas_common.window.clone();
|
||||
self.on_cursor_leave =
|
||||
Some(canvas_common.add_event("pointerout", move |event: PointerEvent| {
|
||||
let modifiers = event::mouse_modifiers(&event);
|
||||
|
||||
// touch events are handled separately
|
||||
// handling them here would produce duplicate mouse events, inconsistent with
|
||||
// other platforms.
|
||||
let device_id =
|
||||
(event.pointer_type() != "touch").then(|| DeviceId::new(event.pointer_id()));
|
||||
|
||||
handler(modifiers, device_id);
|
||||
let pointer_id = event.pointer_id();
|
||||
let device_id = DeviceId::new(pointer_id);
|
||||
let position =
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window));
|
||||
let kind = event::pointer_type(&event, pointer_id);
|
||||
handler(modifiers, device_id, position, kind);
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn on_cursor_enter<F>(&mut self, canvas_common: &Common, mut handler: F)
|
||||
pub fn on_pointer_enter<F>(&mut self, canvas_common: &Common, mut handler: F)
|
||||
where
|
||||
F: 'static + FnMut(ModifiersState, Option<Option<DeviceId>>),
|
||||
F: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, PointerKind),
|
||||
{
|
||||
let window = canvas_common.window.clone();
|
||||
self.on_cursor_enter =
|
||||
Some(canvas_common.add_event("pointerover", move |event: PointerEvent| {
|
||||
let modifiers = event::mouse_modifiers(&event);
|
||||
|
||||
// touch events are handled separately
|
||||
// handling them here would produce duplicate mouse events, inconsistent with
|
||||
// other platforms.
|
||||
let device_id =
|
||||
(event.pointer_type() != "touch").then(|| DeviceId::new(event.pointer_id()));
|
||||
|
||||
handler(modifiers, device_id);
|
||||
let pointer_id = event.pointer_id();
|
||||
let device_id = DeviceId::new(pointer_id);
|
||||
let position =
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window));
|
||||
let kind = event::pointer_type(&event, pointer_id);
|
||||
handler(modifiers, device_id, position, kind);
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn on_mouse_release<M, T>(
|
||||
&mut self,
|
||||
canvas_common: &Common,
|
||||
mut mouse_handler: M,
|
||||
mut touch_handler: T,
|
||||
) where
|
||||
M: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, MouseButton),
|
||||
T: 'static
|
||||
+ FnMut(ModifiersState, Option<DeviceId>, FingerId, PhysicalPosition<f64>, Force),
|
||||
pub fn on_pointer_release<C>(&mut self, canvas_common: &Common, mut handler: C)
|
||||
where
|
||||
C: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, ButtonSource),
|
||||
{
|
||||
let window = canvas_common.window.clone();
|
||||
self.on_pointer_release =
|
||||
Some(canvas_common.add_event("pointerup", move |event: PointerEvent| {
|
||||
let modifiers = event::mouse_modifiers(&event);
|
||||
let pointer_id = event.pointer_id();
|
||||
let kind = event::pointer_type(&event, pointer_id);
|
||||
|
||||
match event.pointer_type().as_str() {
|
||||
"touch" => {
|
||||
let pointer_id = event.pointer_id();
|
||||
touch_handler(
|
||||
modifiers,
|
||||
DeviceId::new(pointer_id),
|
||||
FingerId::new(pointer_id, event.is_primary()),
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window)),
|
||||
Force::Normalized(event.pressure() as f64),
|
||||
)
|
||||
let button = event::mouse_button(&event).expect("no mouse button pressed");
|
||||
|
||||
let source = match kind {
|
||||
PointerKind::Mouse => ButtonSource::Mouse(button),
|
||||
PointerKind::Touch(finger_id) => ButtonSource::Touch {
|
||||
finger_id,
|
||||
force: Some(Force::Normalized(event.pressure().into())),
|
||||
},
|
||||
_ => mouse_handler(
|
||||
modifiers,
|
||||
DeviceId::new(event.pointer_id()),
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window)),
|
||||
event::mouse_button(&event).expect("no mouse button released"),
|
||||
),
|
||||
}
|
||||
PointerKind::Unknown => ButtonSource::Unknown(button.to_id()),
|
||||
};
|
||||
|
||||
handler(
|
||||
modifiers,
|
||||
DeviceId::new(pointer_id),
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window)),
|
||||
source,
|
||||
)
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn on_mouse_press<M, T>(
|
||||
pub fn on_pointer_press<C>(
|
||||
&mut self,
|
||||
canvas_common: &Common,
|
||||
mut mouse_handler: M,
|
||||
mut touch_handler: T,
|
||||
mut handler: C,
|
||||
prevent_default: Rc<Cell<bool>>,
|
||||
) where
|
||||
M: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, MouseButton),
|
||||
T: 'static
|
||||
+ FnMut(ModifiersState, Option<DeviceId>, FingerId, PhysicalPosition<f64>, Force),
|
||||
C: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, ButtonSource),
|
||||
{
|
||||
let window = canvas_common.window.clone();
|
||||
let canvas = canvas_common.raw().clone();
|
||||
|
|
@ -129,75 +118,65 @@ impl PointerHandler {
|
|||
}
|
||||
|
||||
let modifiers = event::mouse_modifiers(&event);
|
||||
let pointer_type = &event.pointer_type();
|
||||
let pointer_id = event.pointer_id();
|
||||
let kind = event::pointer_type(&event, pointer_id);
|
||||
let button = event::mouse_button(&event).expect("no mouse button pressed");
|
||||
|
||||
match pointer_type.as_str() {
|
||||
"touch" => {
|
||||
let pointer_id = event.pointer_id();
|
||||
touch_handler(
|
||||
modifiers,
|
||||
DeviceId::new(pointer_id),
|
||||
FingerId::new(pointer_id, event.is_primary()),
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window)),
|
||||
Force::Normalized(event.pressure() as f64),
|
||||
);
|
||||
let source = match kind {
|
||||
PointerKind::Mouse => {
|
||||
// Error is swallowed here since the error would occur every time the
|
||||
// mouse is clicked when the cursor is
|
||||
// grabbed, and there is probably not a
|
||||
// situation where this could fail, that we
|
||||
// care if it fails.
|
||||
let _e = canvas.set_pointer_capture(pointer_id);
|
||||
|
||||
ButtonSource::Mouse(button)
|
||||
},
|
||||
_ => {
|
||||
let pointer_id = event.pointer_id();
|
||||
|
||||
mouse_handler(
|
||||
modifiers,
|
||||
DeviceId::new(pointer_id),
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window)),
|
||||
event::mouse_button(&event).expect("no mouse button pressed"),
|
||||
);
|
||||
|
||||
if pointer_type == "mouse" {
|
||||
// Error is swallowed here since the error would occur every time the
|
||||
// mouse is clicked when the cursor is
|
||||
// grabbed, and there is probably not a
|
||||
// situation where this could fail, that we
|
||||
// care if it fails.
|
||||
let _e = canvas.set_pointer_capture(pointer_id);
|
||||
}
|
||||
PointerKind::Touch(finger_id) => ButtonSource::Touch {
|
||||
finger_id,
|
||||
force: Some(Force::Normalized(event.pressure().into())),
|
||||
},
|
||||
}
|
||||
PointerKind::Unknown => ButtonSource::Unknown(button.to_id()),
|
||||
};
|
||||
|
||||
handler(
|
||||
modifiers,
|
||||
DeviceId::new(pointer_id),
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window)),
|
||||
source,
|
||||
)
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn on_cursor_move<M, T, B>(
|
||||
pub fn on_pointer_move<C, B>(
|
||||
&mut self,
|
||||
canvas_common: &Common,
|
||||
mut mouse_handler: M,
|
||||
mut touch_handler: T,
|
||||
mut cursor_handler: C,
|
||||
mut button_handler: B,
|
||||
prevent_default: Rc<Cell<bool>>,
|
||||
) where
|
||||
M: 'static
|
||||
+ FnMut(ModifiersState, Option<DeviceId>, &mut dyn Iterator<Item = PhysicalPosition<f64>>),
|
||||
T: 'static
|
||||
C: 'static
|
||||
+ FnMut(
|
||||
ModifiersState,
|
||||
Option<DeviceId>,
|
||||
FingerId,
|
||||
&mut dyn Iterator<Item = (PhysicalPosition<f64>, Force)>,
|
||||
&mut dyn Iterator<Item = (ModifiersState, PhysicalPosition<f64>, PointerSource)>,
|
||||
),
|
||||
B: 'static
|
||||
+ FnMut(
|
||||
ModifiersState,
|
||||
Option<DeviceId>,
|
||||
PhysicalPosition<f64>,
|
||||
ButtonsState,
|
||||
MouseButton,
|
||||
ElementState,
|
||||
ButtonSource,
|
||||
),
|
||||
{
|
||||
let window = canvas_common.window.clone();
|
||||
let canvas = canvas_common.raw().clone();
|
||||
self.on_cursor_move =
|
||||
Some(canvas_common.add_event("pointermove", move |event: PointerEvent| {
|
||||
let modifiers = event::mouse_modifiers(&event);
|
||||
let pointer_id = event.pointer_id();
|
||||
let device_id = DeviceId::new(pointer_id);
|
||||
let kind = event::pointer_type(&event, pointer_id);
|
||||
|
||||
// chorded button event
|
||||
if let Some(button) = event::mouse_button(&event) {
|
||||
|
|
@ -208,11 +187,34 @@ impl PointerHandler {
|
|||
let _ = canvas.focus();
|
||||
}
|
||||
|
||||
let state = if event::mouse_buttons(&event).contains(button.into()) {
|
||||
ElementState::Pressed
|
||||
} else {
|
||||
ElementState::Released
|
||||
};
|
||||
|
||||
let button = match kind {
|
||||
PointerKind::Mouse => ButtonSource::Mouse(button),
|
||||
PointerKind::Touch(finger_id) => {
|
||||
let button_id = button.to_id();
|
||||
|
||||
if button_id != 1 {
|
||||
tracing::error!("unexpected touch button id: {button_id}");
|
||||
}
|
||||
|
||||
ButtonSource::Touch {
|
||||
finger_id,
|
||||
force: Some(Force::Normalized(event.pressure().into())),
|
||||
}
|
||||
},
|
||||
PointerKind::Unknown => todo!(),
|
||||
};
|
||||
|
||||
button_handler(
|
||||
modifiers,
|
||||
event::mouse_modifiers(&event),
|
||||
device_id,
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window)),
|
||||
event::mouse_buttons(&event),
|
||||
state,
|
||||
button,
|
||||
);
|
||||
|
||||
|
|
@ -221,44 +223,24 @@ impl PointerHandler {
|
|||
|
||||
// pointer move event
|
||||
let scale = super::scale_factor(&window);
|
||||
match event.pointer_type().as_str() {
|
||||
"touch" => touch_handler(
|
||||
modifiers,
|
||||
device_id,
|
||||
FingerId::new(pointer_id, event.is_primary()),
|
||||
&mut event::pointer_move_event(event).map(|event| {
|
||||
(
|
||||
event::mouse_position(&event).to_physical(scale),
|
||||
Force::Normalized(event.pressure() as f64),
|
||||
)
|
||||
}),
|
||||
),
|
||||
_ => mouse_handler(
|
||||
modifiers,
|
||||
device_id,
|
||||
&mut event::pointer_move_event(event)
|
||||
.map(|event| event::mouse_position(&event).to_physical(scale)),
|
||||
),
|
||||
};
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn on_touch_cancel<F>(&mut self, canvas_common: &Common, mut handler: F)
|
||||
where
|
||||
F: 'static + FnMut(Option<DeviceId>, FingerId, PhysicalPosition<f64>, Force),
|
||||
{
|
||||
let window = canvas_common.window.clone();
|
||||
self.on_touch_cancel =
|
||||
Some(canvas_common.add_event("pointercancel", move |event: PointerEvent| {
|
||||
if event.pointer_type() == "touch" {
|
||||
let pointer_id = event.pointer_id();
|
||||
handler(
|
||||
DeviceId::new(pointer_id),
|
||||
FingerId::new(pointer_id, event.is_primary()),
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window)),
|
||||
Force::Normalized(event.pressure() as f64),
|
||||
);
|
||||
}
|
||||
cursor_handler(
|
||||
device_id,
|
||||
&mut event::pointer_move_event(event).map(|event| {
|
||||
(
|
||||
event::mouse_modifiers(&event),
|
||||
event::mouse_position(&event).to_physical(scale),
|
||||
match kind {
|
||||
PointerKind::Mouse => PointerSource::Mouse,
|
||||
PointerKind::Touch(finger_id) => PointerSource::Touch {
|
||||
finger_id,
|
||||
force: Some(Force::Normalized(event.pressure().into())),
|
||||
},
|
||||
PointerKind::Unknown => PointerSource::Unknown,
|
||||
},
|
||||
)
|
||||
}),
|
||||
);
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,9 +37,9 @@ use windows_sys::Win32::UI::WindowsAndMessaging::{
|
|||
GetMenu, GetMessageW, KillTimer, LoadCursorW, PeekMessageW, PostMessageW, RegisterClassExW,
|
||||
RegisterWindowMessageA, SetCursor, SetTimer, SetWindowPos, TranslateMessage, CREATESTRUCTW,
|
||||
GWL_STYLE, GWL_USERDATA, HTCAPTION, HTCLIENT, MINMAXINFO, MNC_CLOSE, MSG, NCCALCSIZE_PARAMS,
|
||||
PM_REMOVE, PT_PEN, PT_TOUCH, RI_MOUSE_HWHEEL, RI_MOUSE_WHEEL, SC_MINIMIZE, SC_RESTORE,
|
||||
SIZE_MAXIMIZED, SWP_NOACTIVATE, SWP_NOMOVE, SWP_NOSIZE, SWP_NOZORDER, WHEEL_DELTA, WINDOWPOS,
|
||||
WMSZ_BOTTOM, WMSZ_BOTTOMLEFT, WMSZ_BOTTOMRIGHT, WMSZ_LEFT, WMSZ_RIGHT, WMSZ_TOP, WMSZ_TOPLEFT,
|
||||
PM_REMOVE, PT_TOUCH, RI_MOUSE_HWHEEL, RI_MOUSE_WHEEL, SC_MINIMIZE, SC_RESTORE, SIZE_MAXIMIZED,
|
||||
SWP_NOACTIVATE, SWP_NOMOVE, SWP_NOSIZE, SWP_NOZORDER, WHEEL_DELTA, WINDOWPOS, WMSZ_BOTTOM,
|
||||
WMSZ_BOTTOMLEFT, WMSZ_BOTTOMRIGHT, WMSZ_LEFT, WMSZ_RIGHT, WMSZ_TOP, WMSZ_TOPLEFT,
|
||||
WMSZ_TOPRIGHT, WM_CAPTURECHANGED, WM_CLOSE, WM_CREATE, WM_DESTROY, WM_DPICHANGED,
|
||||
WM_ENTERSIZEMOVE, WM_EXITSIZEMOVE, WM_GETMINMAXINFO, WM_IME_COMPOSITION, WM_IME_ENDCOMPOSITION,
|
||||
WM_IME_SETCONTEXT, WM_IME_STARTCOMPOSITION, WM_INPUT, WM_KEYDOWN, WM_KEYUP, WM_KILLFOCUS,
|
||||
|
|
@ -58,7 +58,7 @@ use crate::application::ApplicationHandler;
|
|||
use crate::dpi::{PhysicalPosition, PhysicalSize};
|
||||
use crate::error::{EventLoopError, RequestError};
|
||||
use crate::event::{
|
||||
Event, FingerId as RootFingerId, Force, Ime, RawKeyEvent, SurfaceSizeWriter, Touch, TouchPhase,
|
||||
Event, FingerId as RootFingerId, Force, Ime, RawKeyEvent, SurfaceSizeWriter, TouchPhase,
|
||||
WindowEvent,
|
||||
};
|
||||
use crate::event_loop::{
|
||||
|
|
@ -1520,7 +1520,8 @@ unsafe fn public_window_callback_inner(
|
|||
},
|
||||
|
||||
WM_MOUSEMOVE => {
|
||||
use crate::event::WindowEvent::{CursorEntered, CursorLeft, CursorMoved};
|
||||
use crate::event::WindowEvent::{PointerEntered, PointerLeft, PointerMoved};
|
||||
use crate::event::{PointerKind, PointerSource};
|
||||
|
||||
let x = super::get_x_lparam(lparam as u32) as i32;
|
||||
let y = super::get_y_lparam(lparam as u32) as i32;
|
||||
|
|
@ -1541,7 +1542,11 @@ unsafe fn public_window_callback_inner(
|
|||
drop(w);
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: CursorEntered { device_id: None },
|
||||
event: PointerEntered {
|
||||
device_id: None,
|
||||
position,
|
||||
kind: PointerKind::Mouse,
|
||||
},
|
||||
});
|
||||
|
||||
// Calling TrackMouseEvent in order to receive mouse leave events.
|
||||
|
|
@ -1562,7 +1567,11 @@ unsafe fn public_window_callback_inner(
|
|||
drop(w);
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: CursorLeft { device_id: None },
|
||||
event: PointerLeft {
|
||||
device_id: None,
|
||||
position: Some(position),
|
||||
kind: PointerKind::Mouse,
|
||||
},
|
||||
});
|
||||
},
|
||||
PointerMoveKind::None => drop(w),
|
||||
|
|
@ -1581,7 +1590,7 @@ unsafe fn public_window_callback_inner(
|
|||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: CursorMoved { device_id: None, position },
|
||||
event: PointerMoved { device_id: None, position, source: PointerSource::Mouse },
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -1589,7 +1598,9 @@ unsafe fn public_window_callback_inner(
|
|||
},
|
||||
|
||||
WM_MOUSELEAVE => {
|
||||
use crate::event::WindowEvent::CursorLeft;
|
||||
use crate::event::PointerKind::Mouse;
|
||||
use crate::event::WindowEvent::PointerLeft;
|
||||
|
||||
{
|
||||
let mut w = userdata.window_state_lock();
|
||||
w.mouse.set_cursor_flags(window, |f| f.set(CursorFlags::IN_WINDOW, false)).ok();
|
||||
|
|
@ -1597,7 +1608,7 @@ unsafe fn public_window_callback_inner(
|
|||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: CursorLeft { device_id: None },
|
||||
event: PointerLeft { device_id: None, position: None, kind: Mouse },
|
||||
});
|
||||
|
||||
result = ProcResult::Value(0);
|
||||
|
|
@ -1660,15 +1671,24 @@ unsafe fn public_window_callback_inner(
|
|||
WM_LBUTTONDOWN => {
|
||||
use crate::event::ElementState::Pressed;
|
||||
use crate::event::MouseButton::Left;
|
||||
use crate::event::WindowEvent::MouseInput;
|
||||
use crate::event::WindowEvent::PointerButton;
|
||||
|
||||
unsafe { capture_mouse(window, &mut userdata.window_state_lock()) };
|
||||
|
||||
update_modifiers(window, userdata);
|
||||
|
||||
let x = super::get_x_lparam(lparam as u32) as i32;
|
||||
let y = super::get_y_lparam(lparam as u32) as i32;
|
||||
let position = PhysicalPosition::new(x as f64, y as f64);
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: MouseInput { device_id: None, state: Pressed, button: Left },
|
||||
event: PointerButton {
|
||||
device_id: None,
|
||||
state: Pressed,
|
||||
position,
|
||||
button: Left.into(),
|
||||
},
|
||||
});
|
||||
result = ProcResult::Value(0);
|
||||
},
|
||||
|
|
@ -1676,15 +1696,24 @@ unsafe fn public_window_callback_inner(
|
|||
WM_LBUTTONUP => {
|
||||
use crate::event::ElementState::Released;
|
||||
use crate::event::MouseButton::Left;
|
||||
use crate::event::WindowEvent::MouseInput;
|
||||
use crate::event::WindowEvent::PointerButton;
|
||||
|
||||
unsafe { release_mouse(userdata.window_state_lock()) };
|
||||
|
||||
update_modifiers(window, userdata);
|
||||
|
||||
let x = super::get_x_lparam(lparam as u32) as i32;
|
||||
let y = super::get_y_lparam(lparam as u32) as i32;
|
||||
let position = PhysicalPosition::new(x as f64, y as f64);
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: MouseInput { device_id: None, state: Released, button: Left },
|
||||
event: PointerButton {
|
||||
device_id: None,
|
||||
state: Released,
|
||||
position,
|
||||
button: Left.into(),
|
||||
},
|
||||
});
|
||||
result = ProcResult::Value(0);
|
||||
},
|
||||
|
|
@ -1692,15 +1721,24 @@ unsafe fn public_window_callback_inner(
|
|||
WM_RBUTTONDOWN => {
|
||||
use crate::event::ElementState::Pressed;
|
||||
use crate::event::MouseButton::Right;
|
||||
use crate::event::WindowEvent::MouseInput;
|
||||
use crate::event::WindowEvent::PointerButton;
|
||||
|
||||
unsafe { capture_mouse(window, &mut userdata.window_state_lock()) };
|
||||
|
||||
update_modifiers(window, userdata);
|
||||
|
||||
let x = super::get_x_lparam(lparam as u32) as i32;
|
||||
let y = super::get_y_lparam(lparam as u32) as i32;
|
||||
let position = PhysicalPosition::new(x as f64, y as f64);
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: MouseInput { device_id: None, state: Pressed, button: Right },
|
||||
event: PointerButton {
|
||||
device_id: None,
|
||||
state: Pressed,
|
||||
position,
|
||||
button: Right.into(),
|
||||
},
|
||||
});
|
||||
result = ProcResult::Value(0);
|
||||
},
|
||||
|
|
@ -1708,15 +1746,24 @@ unsafe fn public_window_callback_inner(
|
|||
WM_RBUTTONUP => {
|
||||
use crate::event::ElementState::Released;
|
||||
use crate::event::MouseButton::Right;
|
||||
use crate::event::WindowEvent::MouseInput;
|
||||
use crate::event::WindowEvent::PointerButton;
|
||||
|
||||
unsafe { release_mouse(userdata.window_state_lock()) };
|
||||
|
||||
update_modifiers(window, userdata);
|
||||
|
||||
let x = super::get_x_lparam(lparam as u32) as i32;
|
||||
let y = super::get_y_lparam(lparam as u32) as i32;
|
||||
let position = PhysicalPosition::new(x as f64, y as f64);
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: MouseInput { device_id: None, state: Released, button: Right },
|
||||
event: PointerButton {
|
||||
device_id: None,
|
||||
state: Released,
|
||||
position,
|
||||
button: Right.into(),
|
||||
},
|
||||
});
|
||||
result = ProcResult::Value(0);
|
||||
},
|
||||
|
|
@ -1724,15 +1771,24 @@ unsafe fn public_window_callback_inner(
|
|||
WM_MBUTTONDOWN => {
|
||||
use crate::event::ElementState::Pressed;
|
||||
use crate::event::MouseButton::Middle;
|
||||
use crate::event::WindowEvent::MouseInput;
|
||||
use crate::event::WindowEvent::PointerButton;
|
||||
|
||||
unsafe { capture_mouse(window, &mut userdata.window_state_lock()) };
|
||||
|
||||
update_modifiers(window, userdata);
|
||||
|
||||
let x = super::get_x_lparam(lparam as u32) as i32;
|
||||
let y = super::get_y_lparam(lparam as u32) as i32;
|
||||
let position = PhysicalPosition::new(x as f64, y as f64);
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: MouseInput { device_id: None, state: Pressed, button: Middle },
|
||||
event: PointerButton {
|
||||
device_id: None,
|
||||
state: Pressed,
|
||||
position,
|
||||
button: Middle.into(),
|
||||
},
|
||||
});
|
||||
result = ProcResult::Value(0);
|
||||
},
|
||||
|
|
@ -1740,15 +1796,24 @@ unsafe fn public_window_callback_inner(
|
|||
WM_MBUTTONUP => {
|
||||
use crate::event::ElementState::Released;
|
||||
use crate::event::MouseButton::Middle;
|
||||
use crate::event::WindowEvent::MouseInput;
|
||||
use crate::event::WindowEvent::PointerButton;
|
||||
|
||||
unsafe { release_mouse(userdata.window_state_lock()) };
|
||||
|
||||
update_modifiers(window, userdata);
|
||||
|
||||
let x = super::get_x_lparam(lparam as u32) as i32;
|
||||
let y = super::get_y_lparam(lparam as u32) as i32;
|
||||
let position = PhysicalPosition::new(x as f64, y as f64);
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: MouseInput { device_id: None, state: Released, button: Middle },
|
||||
event: PointerButton {
|
||||
device_id: None,
|
||||
state: Released,
|
||||
position,
|
||||
button: Middle.into(),
|
||||
},
|
||||
});
|
||||
result = ProcResult::Value(0);
|
||||
},
|
||||
|
|
@ -1756,23 +1821,29 @@ unsafe fn public_window_callback_inner(
|
|||
WM_XBUTTONDOWN => {
|
||||
use crate::event::ElementState::Pressed;
|
||||
use crate::event::MouseButton::{Back, Forward, Other};
|
||||
use crate::event::WindowEvent::MouseInput;
|
||||
use crate::event::WindowEvent::PointerButton;
|
||||
let xbutton = super::get_xbutton_wparam(wparam as u32);
|
||||
|
||||
unsafe { capture_mouse(window, &mut userdata.window_state_lock()) };
|
||||
|
||||
update_modifiers(window, userdata);
|
||||
|
||||
let x = super::get_x_lparam(lparam as u32) as i32;
|
||||
let y = super::get_y_lparam(lparam as u32) as i32;
|
||||
let position = PhysicalPosition::new(x as f64, y as f64);
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: MouseInput {
|
||||
event: PointerButton {
|
||||
device_id: None,
|
||||
state: Pressed,
|
||||
position,
|
||||
button: match xbutton {
|
||||
1 => Back,
|
||||
2 => Forward,
|
||||
_ => Other(xbutton),
|
||||
},
|
||||
}
|
||||
.into(),
|
||||
},
|
||||
});
|
||||
result = ProcResult::Value(0);
|
||||
|
|
@ -1781,23 +1852,29 @@ unsafe fn public_window_callback_inner(
|
|||
WM_XBUTTONUP => {
|
||||
use crate::event::ElementState::Released;
|
||||
use crate::event::MouseButton::{Back, Forward, Other};
|
||||
use crate::event::WindowEvent::MouseInput;
|
||||
use crate::event::WindowEvent::PointerButton;
|
||||
let xbutton = super::get_xbutton_wparam(wparam as u32);
|
||||
|
||||
unsafe { release_mouse(userdata.window_state_lock()) };
|
||||
|
||||
update_modifiers(window, userdata);
|
||||
|
||||
let x = super::get_x_lparam(lparam as u32) as i32;
|
||||
let y = super::get_y_lparam(lparam as u32) as i32;
|
||||
let position = PhysicalPosition::new(x as f64, y as f64);
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: MouseInput {
|
||||
event: PointerButton {
|
||||
device_id: None,
|
||||
state: Released,
|
||||
position,
|
||||
button: match xbutton {
|
||||
1 => Back,
|
||||
2 => Forward,
|
||||
_ => Other(xbutton),
|
||||
},
|
||||
}
|
||||
.into(),
|
||||
},
|
||||
});
|
||||
result = ProcResult::Value(0);
|
||||
|
|
@ -1815,6 +1892,10 @@ unsafe fn public_window_callback_inner(
|
|||
},
|
||||
|
||||
WM_TOUCH => {
|
||||
use crate::event::ButtonSource::Touch;
|
||||
use crate::event::ElementState::{Pressed, Released};
|
||||
use crate::event::{PointerKind, PointerSource};
|
||||
|
||||
let pcount = super::loword(wparam as u32) as usize;
|
||||
let mut inputs = Vec::with_capacity(pcount);
|
||||
let htouch = lparam;
|
||||
|
|
@ -1828,36 +1909,70 @@ unsafe fn public_window_callback_inner(
|
|||
} {
|
||||
unsafe { inputs.set_len(pcount) };
|
||||
for input in &inputs {
|
||||
let mut location = POINT { x: input.x / 100, y: input.y / 100 };
|
||||
let mut position = POINT { x: input.x / 100, y: input.y / 100 };
|
||||
|
||||
if unsafe { ScreenToClient(window, &mut location) } == false.into() {
|
||||
if unsafe { ScreenToClient(window, &mut position) } == false.into() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let x = location.x as f64 + (input.x % 100) as f64 / 100f64;
|
||||
let y = location.y as f64 + (input.y % 100) as f64 / 100f64;
|
||||
let location = PhysicalPosition::new(x, y);
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: WindowEvent::Touch(Touch {
|
||||
phase: if util::has_flag(input.dwFlags, TOUCHEVENTF_DOWN) {
|
||||
TouchPhase::Started
|
||||
} else if util::has_flag(input.dwFlags, TOUCHEVENTF_UP) {
|
||||
TouchPhase::Ended
|
||||
} else if util::has_flag(input.dwFlags, TOUCHEVENTF_MOVE) {
|
||||
TouchPhase::Moved
|
||||
} else {
|
||||
continue;
|
||||
},
|
||||
location,
|
||||
force: None, // WM_TOUCH doesn't support pressure information
|
||||
finger_id: RootFingerId(FingerId {
|
||||
id: input.dwID,
|
||||
primary: util::has_flag(input.dwFlags, TOUCHEVENTF_PRIMARY),
|
||||
}),
|
||||
device_id: None,
|
||||
}),
|
||||
let x = position.x as f64 + (input.x % 100) as f64 / 100f64;
|
||||
let y = position.y as f64 + (input.y % 100) as f64 / 100f64;
|
||||
let position = PhysicalPosition::new(x, y);
|
||||
|
||||
let window_id = CoreWindowId(WindowId(window));
|
||||
let finger_id = RootFingerId(FingerId {
|
||||
id: input.dwID,
|
||||
primary: util::has_flag(input.dwFlags, TOUCHEVENTF_PRIMARY),
|
||||
});
|
||||
|
||||
if util::has_flag(input.dwFlags, TOUCHEVENTF_DOWN) {
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerEntered {
|
||||
device_id: None,
|
||||
position,
|
||||
kind: PointerKind::Touch(finger_id),
|
||||
},
|
||||
});
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerButton {
|
||||
device_id: None,
|
||||
state: Pressed,
|
||||
position,
|
||||
button: Touch { finger_id, force: None },
|
||||
},
|
||||
});
|
||||
} else if util::has_flag(input.dwFlags, TOUCHEVENTF_UP) {
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerButton {
|
||||
device_id: None,
|
||||
state: Released,
|
||||
position,
|
||||
button: Touch { finger_id, force: None },
|
||||
},
|
||||
});
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerLeft {
|
||||
device_id: None,
|
||||
position: Some(position),
|
||||
kind: PointerKind::Touch(finger_id),
|
||||
},
|
||||
});
|
||||
} else if util::has_flag(input.dwFlags, TOUCHEVENTF_MOVE) {
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerMoved {
|
||||
device_id: None,
|
||||
position,
|
||||
source: PointerSource::Touch { finger_id, force: None },
|
||||
},
|
||||
});
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
unsafe { CloseTouchInputHandle(htouch) };
|
||||
|
|
@ -1865,6 +1980,9 @@ unsafe fn public_window_callback_inner(
|
|||
},
|
||||
|
||||
WM_POINTERDOWN | WM_POINTERUPDATE | WM_POINTERUP => {
|
||||
use crate::event::ElementState::{Pressed, Released};
|
||||
use crate::event::{ButtonSource, PointerKind, PointerSource};
|
||||
|
||||
if let (
|
||||
Some(GetPointerFrameInfoHistory),
|
||||
Some(SkipPointerFrameMessages),
|
||||
|
|
@ -1949,67 +2067,100 @@ unsafe fn public_window_callback_inner(
|
|||
continue;
|
||||
}
|
||||
|
||||
let force = match pointer_info.pointerType {
|
||||
PT_TOUCH => {
|
||||
let mut touch_info = mem::MaybeUninit::uninit();
|
||||
util::GET_POINTER_TOUCH_INFO.and_then(|GetPointerTouchInfo| {
|
||||
match unsafe {
|
||||
GetPointerTouchInfo(
|
||||
pointer_info.pointerId,
|
||||
touch_info.as_mut_ptr(),
|
||||
)
|
||||
} {
|
||||
0 => None,
|
||||
_ => normalize_pointer_pressure(unsafe {
|
||||
touch_info.assume_init().pressure
|
||||
}),
|
||||
}
|
||||
})
|
||||
},
|
||||
PT_PEN => {
|
||||
let mut pen_info = mem::MaybeUninit::uninit();
|
||||
util::GET_POINTER_PEN_INFO.and_then(|GetPointerPenInfo| {
|
||||
match unsafe {
|
||||
GetPointerPenInfo(pointer_info.pointerId, pen_info.as_mut_ptr())
|
||||
} {
|
||||
0 => None,
|
||||
_ => normalize_pointer_pressure(unsafe {
|
||||
pen_info.assume_init().pressure
|
||||
}),
|
||||
}
|
||||
})
|
||||
},
|
||||
_ => None,
|
||||
let force = if let PT_TOUCH = pointer_info.pointerType {
|
||||
let mut touch_info = mem::MaybeUninit::uninit();
|
||||
util::GET_POINTER_TOUCH_INFO.and_then(|GetPointerTouchInfo| {
|
||||
match unsafe {
|
||||
GetPointerTouchInfo(pointer_info.pointerId, touch_info.as_mut_ptr())
|
||||
} {
|
||||
0 => None,
|
||||
_ => normalize_pointer_pressure(unsafe {
|
||||
touch_info.assume_init().pressure
|
||||
}),
|
||||
}
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let x = location.x as f64 + x.fract();
|
||||
let y = location.y as f64 + y.fract();
|
||||
let location = PhysicalPosition::new(x, y);
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: WindowEvent::Touch(Touch {
|
||||
phase: if util::has_flag(pointer_info.pointerFlags, POINTER_FLAG_DOWN) {
|
||||
TouchPhase::Started
|
||||
} else if util::has_flag(pointer_info.pointerFlags, POINTER_FLAG_UP) {
|
||||
TouchPhase::Ended
|
||||
} else if util::has_flag(pointer_info.pointerFlags, POINTER_FLAG_UPDATE)
|
||||
{
|
||||
TouchPhase::Moved
|
||||
} else {
|
||||
continue;
|
||||
},
|
||||
location,
|
||||
force,
|
||||
finger_id: RootFingerId(FingerId {
|
||||
id: pointer_info.pointerId,
|
||||
primary: util::has_flag(
|
||||
pointer_info.pointerFlags,
|
||||
POINTER_FLAG_PRIMARY,
|
||||
),
|
||||
}),
|
||||
device_id: None,
|
||||
}),
|
||||
let position = PhysicalPosition::new(x, y);
|
||||
|
||||
let window_id = CoreWindowId(WindowId(window));
|
||||
let finger_id = RootFingerId(FingerId {
|
||||
id: pointer_info.pointerId,
|
||||
primary: util::has_flag(pointer_info.pointerFlags, POINTER_FLAG_PRIMARY),
|
||||
});
|
||||
|
||||
if util::has_flag(pointer_info.pointerFlags, POINTER_FLAG_DOWN) {
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerEntered {
|
||||
device_id: None,
|
||||
position,
|
||||
kind: if let PT_TOUCH = pointer_info.pointerType {
|
||||
PointerKind::Touch(finger_id)
|
||||
} else {
|
||||
PointerKind::Unknown
|
||||
},
|
||||
},
|
||||
});
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerButton {
|
||||
device_id: None,
|
||||
state: Pressed,
|
||||
position,
|
||||
button: if let PT_TOUCH = pointer_info.pointerType {
|
||||
ButtonSource::Touch { finger_id, force }
|
||||
} else {
|
||||
ButtonSource::Unknown(0)
|
||||
},
|
||||
},
|
||||
});
|
||||
} else if util::has_flag(pointer_info.pointerFlags, POINTER_FLAG_UP) {
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerButton {
|
||||
device_id: None,
|
||||
state: Released,
|
||||
position,
|
||||
button: if let PT_TOUCH = pointer_info.pointerType {
|
||||
ButtonSource::Touch { finger_id, force }
|
||||
} else {
|
||||
ButtonSource::Unknown(0)
|
||||
},
|
||||
},
|
||||
});
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerLeft {
|
||||
device_id: None,
|
||||
position: Some(position),
|
||||
kind: if let PT_TOUCH = pointer_info.pointerType {
|
||||
PointerKind::Touch(finger_id)
|
||||
} else {
|
||||
PointerKind::Unknown
|
||||
},
|
||||
},
|
||||
});
|
||||
} else if util::has_flag(pointer_info.pointerFlags, POINTER_FLAG_UPDATE) {
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerMoved {
|
||||
device_id: None,
|
||||
position,
|
||||
source: if let PT_TOUCH = pointer_info.pointerType {
|
||||
PointerSource::Touch { finger_id, force }
|
||||
} else {
|
||||
PointerSource::Unknown
|
||||
},
|
||||
},
|
||||
});
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
unsafe { SkipPointerFrameMessages(pointer_id) };
|
||||
|
|
@ -2431,7 +2582,7 @@ unsafe extern "system" fn thread_event_target_callback(
|
|||
}
|
||||
|
||||
unsafe fn handle_raw_input(userdata: &ThreadMsgTargetData, data: RAWINPUT) {
|
||||
use crate::event::DeviceEvent::{Button, Key, MouseMotion, MouseWheel};
|
||||
use crate::event::DeviceEvent::{Button, Key, MouseWheel, PointerMotion};
|
||||
use crate::event::ElementState::{Pressed, Released};
|
||||
use crate::event::MouseScrollDelta::LineDelta;
|
||||
|
||||
|
|
@ -2447,7 +2598,7 @@ unsafe fn handle_raw_input(userdata: &ThreadMsgTargetData, data: RAWINPUT) {
|
|||
if x != 0.0 || y != 0.0 {
|
||||
userdata.send_event(Event::DeviceEvent {
|
||||
device_id,
|
||||
event: MouseMotion { delta: (x, y) },
|
||||
event: PointerMotion { delta: (x, y) },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use windows_sys::Win32::UI::HiDpi::{
|
|||
DPI_AWARENESS_CONTEXT, MONITOR_DPI_TYPE, PROCESS_DPI_AWARENESS,
|
||||
};
|
||||
use windows_sys::Win32::UI::Input::KeyboardAndMouse::GetActiveWindow;
|
||||
use windows_sys::Win32::UI::Input::Pointer::{POINTER_INFO, POINTER_PEN_INFO, POINTER_TOUCH_INFO};
|
||||
use windows_sys::Win32::UI::Input::Pointer::{POINTER_INFO, POINTER_TOUCH_INFO};
|
||||
use windows_sys::Win32::UI::WindowsAndMessaging::{
|
||||
ClipCursor, GetClientRect, GetClipCursor, GetSystemMetrics, GetWindowPlacement, GetWindowRect,
|
||||
IsIconic, ShowCursor, IDC_APPSTARTING, IDC_ARROW, IDC_CROSS, IDC_HAND, IDC_HELP, IDC_IBEAM,
|
||||
|
|
@ -244,9 +244,6 @@ pub type GetPointerDeviceRects = unsafe extern "system" fn(
|
|||
pub type GetPointerTouchInfo =
|
||||
unsafe extern "system" fn(pointerId: u32, touchInfo: *mut POINTER_TOUCH_INFO) -> BOOL;
|
||||
|
||||
pub type GetPointerPenInfo =
|
||||
unsafe extern "system" fn(pointId: u32, penInfo: *mut POINTER_PEN_INFO) -> BOOL;
|
||||
|
||||
pub(crate) static GET_DPI_FOR_WINDOW: Lazy<Option<GetDpiForWindow>> =
|
||||
Lazy::new(|| get_function!("user32.dll", GetDpiForWindow));
|
||||
pub(crate) static ADJUST_WINDOW_RECT_EX_FOR_DPI: Lazy<Option<AdjustWindowRectExForDpi>> =
|
||||
|
|
@ -269,5 +266,3 @@ pub(crate) static GET_POINTER_DEVICE_RECTS: Lazy<Option<GetPointerDeviceRects>>
|
|||
Lazy::new(|| get_function!("user32.dll", GetPointerDeviceRects));
|
||||
pub(crate) static GET_POINTER_TOUCH_INFO: Lazy<Option<GetPointerTouchInfo>> =
|
||||
Lazy::new(|| get_function!("user32.dll", GetPointerTouchInfo));
|
||||
pub(crate) static GET_POINTER_PEN_INFO: Lazy<Option<GetPointerPenInfo>> =
|
||||
Lazy::new(|| get_function!("user32.dll", GetPointerPenInfo));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue