mirror of
https://github.com/rust-windowing/winit.git
synced 2026-06-27 23:23:14 -04:00
This commit also drops 'Theme' trait with its support types in favor of 'FallbackFrame' meaning that winit will use some predefined frame for the time being, since porting 'ConceptFrame' will require adding font rendering librarires right into winit, which is not desired. Fixes #1889.
306 lines
11 KiB
Rust
306 lines
11 KiB
Rust
//! Handlers for the pointers we're using.
|
|
|
|
use std::cell::RefCell;
|
|
use std::rc::Rc;
|
|
|
|
use sctk::reexports::client::protocol::wl_pointer::{self, Event as PointerEvent};
|
|
use sctk::reexports::client::protocol::wl_seat::WlSeat;
|
|
use sctk::reexports::protocols::unstable::relative_pointer::v1::client::zwp_relative_pointer_v1::Event as RelativePointerEvent;
|
|
|
|
use sctk::seat::pointer::ThemedPointer;
|
|
|
|
use crate::dpi::LogicalPosition;
|
|
use crate::event::{
|
|
DeviceEvent, ElementState, MouseButton, MouseScrollDelta, TouchPhase, WindowEvent,
|
|
};
|
|
use crate::platform_impl::wayland::event_loop::WinitState;
|
|
use crate::platform_impl::wayland::{self, DeviceId};
|
|
|
|
use super::{PointerData, WinitPointer};
|
|
|
|
// These values are comming from <linux/input-event-codes.h>.
|
|
const BTN_LEFT: u32 = 0x110;
|
|
const BTN_RIGHT: u32 = 0x111;
|
|
const BTN_MIDDLE: u32 = 0x112;
|
|
|
|
#[inline]
|
|
pub(super) fn handle_pointer(
|
|
pointer: ThemedPointer,
|
|
event: PointerEvent,
|
|
pointer_data: &Rc<RefCell<PointerData>>,
|
|
winit_state: &mut WinitState,
|
|
seat: WlSeat,
|
|
) {
|
|
let event_sink = &mut winit_state.event_sink;
|
|
let mut pointer_data = pointer_data.borrow_mut();
|
|
match event {
|
|
PointerEvent::Enter {
|
|
surface,
|
|
surface_x,
|
|
surface_y,
|
|
serial,
|
|
..
|
|
} => {
|
|
pointer_data.latest_serial.replace(serial);
|
|
|
|
let window_id = wayland::make_wid(&surface);
|
|
if !winit_state.window_map.contains_key(&window_id) {
|
|
return;
|
|
}
|
|
let window_handle = match winit_state.window_map.get_mut(&window_id) {
|
|
Some(window_handle) => window_handle,
|
|
None => return,
|
|
};
|
|
|
|
let scale_factor = sctk::get_surface_scale_factor(&surface) as f64;
|
|
pointer_data.surface = Some(surface);
|
|
|
|
// Notify window that pointer entered the surface.
|
|
let winit_pointer = WinitPointer {
|
|
pointer,
|
|
confined_pointer: Rc::downgrade(&pointer_data.confined_pointer),
|
|
pointer_constraints: pointer_data.pointer_constraints.clone(),
|
|
latest_serial: pointer_data.latest_serial.clone(),
|
|
seat,
|
|
};
|
|
window_handle.pointer_entered(winit_pointer);
|
|
|
|
event_sink.push_window_event(
|
|
WindowEvent::CursorEntered {
|
|
device_id: crate::event::DeviceId(crate::platform_impl::DeviceId::Wayland(
|
|
DeviceId,
|
|
)),
|
|
},
|
|
window_id,
|
|
);
|
|
|
|
let position = LogicalPosition::new(surface_x, surface_y).to_physical(scale_factor);
|
|
|
|
event_sink.push_window_event(
|
|
WindowEvent::CursorMoved {
|
|
device_id: crate::event::DeviceId(crate::platform_impl::DeviceId::Wayland(
|
|
DeviceId,
|
|
)),
|
|
position,
|
|
modifiers: *pointer_data.modifiers_state.borrow(),
|
|
},
|
|
window_id,
|
|
);
|
|
}
|
|
PointerEvent::Leave { surface, serial } => {
|
|
pointer_data.surface = None;
|
|
pointer_data.latest_serial.replace(serial);
|
|
|
|
let window_id = wayland::make_wid(&surface);
|
|
|
|
let window_handle = match winit_state.window_map.get_mut(&window_id) {
|
|
Some(window_handle) => window_handle,
|
|
None => return,
|
|
};
|
|
|
|
// Notify a window that pointer is no longer observing it.
|
|
let winit_pointer = WinitPointer {
|
|
pointer,
|
|
confined_pointer: Rc::downgrade(&pointer_data.confined_pointer),
|
|
pointer_constraints: pointer_data.pointer_constraints.clone(),
|
|
latest_serial: pointer_data.latest_serial.clone(),
|
|
seat,
|
|
};
|
|
window_handle.pointer_left(winit_pointer);
|
|
|
|
event_sink.push_window_event(
|
|
WindowEvent::CursorLeft {
|
|
device_id: crate::event::DeviceId(crate::platform_impl::DeviceId::Wayland(
|
|
DeviceId,
|
|
)),
|
|
},
|
|
window_id,
|
|
);
|
|
}
|
|
PointerEvent::Motion {
|
|
surface_x,
|
|
surface_y,
|
|
..
|
|
} => {
|
|
let surface = match pointer_data.surface.as_ref() {
|
|
Some(surface) => surface,
|
|
None => return,
|
|
};
|
|
|
|
let window_id = wayland::make_wid(surface);
|
|
|
|
let scale_factor = sctk::get_surface_scale_factor(surface) as f64;
|
|
let position = LogicalPosition::new(surface_x, surface_y).to_physical(scale_factor);
|
|
|
|
event_sink.push_window_event(
|
|
WindowEvent::CursorMoved {
|
|
device_id: crate::event::DeviceId(crate::platform_impl::DeviceId::Wayland(
|
|
DeviceId,
|
|
)),
|
|
position,
|
|
modifiers: *pointer_data.modifiers_state.borrow(),
|
|
},
|
|
window_id,
|
|
);
|
|
}
|
|
PointerEvent::Button {
|
|
button,
|
|
state,
|
|
serial,
|
|
..
|
|
} => {
|
|
pointer_data.latest_serial.replace(serial);
|
|
let window_id = match pointer_data.surface.as_ref().map(wayland::make_wid) {
|
|
Some(window_id) => window_id,
|
|
None => return,
|
|
};
|
|
|
|
let state = match state {
|
|
wl_pointer::ButtonState::Pressed => ElementState::Pressed,
|
|
wl_pointer::ButtonState::Released => ElementState::Released,
|
|
_ => unreachable!(),
|
|
};
|
|
|
|
let button = match button {
|
|
BTN_LEFT => MouseButton::Left,
|
|
BTN_RIGHT => MouseButton::Right,
|
|
BTN_MIDDLE => MouseButton::Middle,
|
|
button => MouseButton::Other(button as u16),
|
|
};
|
|
|
|
event_sink.push_window_event(
|
|
WindowEvent::MouseInput {
|
|
device_id: crate::event::DeviceId(crate::platform_impl::DeviceId::Wayland(
|
|
DeviceId,
|
|
)),
|
|
state,
|
|
button,
|
|
modifiers: *pointer_data.modifiers_state.borrow(),
|
|
},
|
|
window_id,
|
|
);
|
|
}
|
|
PointerEvent::Axis { axis, value, .. } => {
|
|
let surface = match pointer_data.surface.as_ref() {
|
|
Some(surface) => surface,
|
|
None => return,
|
|
};
|
|
|
|
let window_id = wayland::make_wid(surface);
|
|
|
|
if pointer.as_ref().version() < 5 {
|
|
let (mut x, mut y) = (0.0, 0.0);
|
|
|
|
// Old seat compatibility.
|
|
match axis {
|
|
// Wayland vertical sign convention is the inverse of winit.
|
|
wl_pointer::Axis::VerticalScroll => y -= value as f32,
|
|
wl_pointer::Axis::HorizontalScroll => x += value as f32,
|
|
_ => unreachable!(),
|
|
}
|
|
|
|
let scale_factor = sctk::get_surface_scale_factor(surface) as f64;
|
|
let delta = LogicalPosition::new(x as f64, y as f64).to_physical(scale_factor);
|
|
|
|
event_sink.push_window_event(
|
|
WindowEvent::MouseWheel {
|
|
device_id: crate::event::DeviceId(crate::platform_impl::DeviceId::Wayland(
|
|
DeviceId,
|
|
)),
|
|
delta: MouseScrollDelta::PixelDelta(delta),
|
|
phase: TouchPhase::Moved,
|
|
modifiers: *pointer_data.modifiers_state.borrow(),
|
|
},
|
|
window_id,
|
|
);
|
|
} else {
|
|
let (mut x, mut y) = pointer_data.axis_data.axis_buffer.unwrap_or((0.0, 0.0));
|
|
match axis {
|
|
// Wayland vertical sign convention is the inverse of winit.
|
|
wl_pointer::Axis::VerticalScroll => y -= value as f32,
|
|
wl_pointer::Axis::HorizontalScroll => x += value as f32,
|
|
_ => unreachable!(),
|
|
}
|
|
|
|
pointer_data.axis_data.axis_buffer = Some((x, y));
|
|
|
|
pointer_data.axis_data.axis_state = match pointer_data.axis_data.axis_state {
|
|
TouchPhase::Started | TouchPhase::Moved => TouchPhase::Moved,
|
|
_ => TouchPhase::Started,
|
|
}
|
|
}
|
|
}
|
|
PointerEvent::AxisDiscrete { axis, discrete } => {
|
|
let (mut x, mut y) = pointer_data
|
|
.axis_data
|
|
.axis_discrete_buffer
|
|
.unwrap_or((0., 0.));
|
|
|
|
match axis {
|
|
// Wayland vertical sign convention is the inverse of winit.
|
|
wl_pointer::Axis::VerticalScroll => y -= discrete as f32,
|
|
wl_pointer::Axis::HorizontalScroll => x += discrete as f32,
|
|
_ => unreachable!(),
|
|
}
|
|
|
|
pointer_data.axis_data.axis_discrete_buffer = Some((x, y));
|
|
|
|
pointer_data.axis_data.axis_state = match pointer_data.axis_data.axis_state {
|
|
TouchPhase::Started | TouchPhase::Moved => TouchPhase::Moved,
|
|
_ => TouchPhase::Started,
|
|
}
|
|
}
|
|
PointerEvent::AxisSource { .. } => (),
|
|
PointerEvent::AxisStop { .. } => {
|
|
pointer_data.axis_data.axis_state = TouchPhase::Ended;
|
|
}
|
|
PointerEvent::Frame => {
|
|
let axis_buffer = pointer_data.axis_data.axis_buffer.take();
|
|
let axis_discrete_buffer = pointer_data.axis_data.axis_discrete_buffer.take();
|
|
|
|
let surface = match pointer_data.surface.as_ref() {
|
|
Some(surface) => surface,
|
|
None => return,
|
|
};
|
|
let window_id = wayland::make_wid(surface);
|
|
|
|
let window_event = if let Some((x, y)) = axis_discrete_buffer {
|
|
WindowEvent::MouseWheel {
|
|
device_id: crate::event::DeviceId(crate::platform_impl::DeviceId::Wayland(
|
|
DeviceId,
|
|
)),
|
|
delta: MouseScrollDelta::LineDelta(x, y),
|
|
phase: pointer_data.axis_data.axis_state,
|
|
modifiers: *pointer_data.modifiers_state.borrow(),
|
|
}
|
|
} else if let Some((x, y)) = axis_buffer {
|
|
let scale_factor = sctk::get_surface_scale_factor(surface) as f64;
|
|
let delta = LogicalPosition::new(x, y).to_physical(scale_factor);
|
|
|
|
WindowEvent::MouseWheel {
|
|
device_id: crate::event::DeviceId(crate::platform_impl::DeviceId::Wayland(
|
|
DeviceId,
|
|
)),
|
|
delta: MouseScrollDelta::PixelDelta(delta),
|
|
phase: pointer_data.axis_data.axis_state,
|
|
modifiers: *pointer_data.modifiers_state.borrow(),
|
|
}
|
|
} else {
|
|
return;
|
|
};
|
|
|
|
event_sink.push_window_event(window_event, window_id);
|
|
}
|
|
_ => (),
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub(super) fn handle_relative_pointer(event: RelativePointerEvent, winit_state: &mut WinitState) {
|
|
if let RelativePointerEvent::RelativeMotion { dx, dy, .. } = event {
|
|
winit_state
|
|
.event_sink
|
|
.push_device_event(DeviceEvent::MouseMotion { delta: (dx, dy) }, DeviceId)
|
|
}
|
|
}
|