2017-11-11 10:03:42 +01:00
|
|
|
use std::sync::{Arc, Mutex};
|
|
|
|
|
|
2019-06-21 11:33:15 -04:00
|
|
|
use crate::event::{
|
2019-06-25 12:00:41 +03:00
|
|
|
DeviceEvent, ElementState, ModifiersState, MouseButton, MouseScrollDelta, TouchPhase,
|
|
|
|
|
WindowEvent,
|
2019-06-21 11:33:15 -04:00
|
|
|
};
|
2017-11-11 10:03:42 +01:00
|
|
|
|
2019-10-03 16:02:59 +03:00
|
|
|
use super::{
|
2020-01-04 01:31:23 -05:00
|
|
|
event_loop::{CursorManager, EventsSink},
|
2020-01-11 11:45:52 +03:00
|
|
|
make_wid,
|
2019-10-03 16:02:59 +03:00
|
|
|
window::WindowStore,
|
|
|
|
|
DeviceId,
|
|
|
|
|
};
|
2017-11-11 10:03:42 +01:00
|
|
|
|
2020-01-11 11:45:52 +03:00
|
|
|
use smithay_client_toolkit::surface;
|
|
|
|
|
|
2019-06-21 11:33:15 -04:00
|
|
|
use smithay_client_toolkit::reexports::client::protocol::{
|
|
|
|
|
wl_pointer::{self, Event as PtrEvent, WlPointer},
|
|
|
|
|
wl_seat,
|
|
|
|
|
};
|
2017-11-11 10:03:42 +01:00
|
|
|
|
2019-06-25 12:00:41 +03:00
|
|
|
use smithay_client_toolkit::reexports::protocols::unstable::relative_pointer::v1::client::{
|
|
|
|
|
zwp_relative_pointer_manager_v1::ZwpRelativePointerManagerV1, zwp_relative_pointer_v1::Event,
|
|
|
|
|
zwp_relative_pointer_v1::ZwpRelativePointerV1,
|
|
|
|
|
};
|
|
|
|
|
|
2019-10-02 03:25:59 +02:00
|
|
|
use smithay_client_toolkit::reexports::protocols::unstable::pointer_constraints::v1::client::{
|
|
|
|
|
zwp_locked_pointer_v1::ZwpLockedPointerV1, zwp_pointer_constraints_v1::Lifetime,
|
|
|
|
|
zwp_pointer_constraints_v1::ZwpPointerConstraintsV1,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
use smithay_client_toolkit::reexports::client::protocol::wl_surface::WlSurface;
|
|
|
|
|
|
2020-01-04 01:31:23 -05:00
|
|
|
pub fn implement_pointer(
|
2019-02-21 10:51:43 +01:00
|
|
|
seat: &wl_seat::WlSeat,
|
2020-01-04 01:31:23 -05:00
|
|
|
sink: EventsSink,
|
2018-05-05 19:36:34 +02:00
|
|
|
store: Arc<Mutex<WindowStore>>,
|
2018-10-18 10:34:02 +08:00
|
|
|
modifiers_tracker: Arc<Mutex<ModifiersState>>,
|
2019-10-03 16:02:59 +03:00
|
|
|
cursor_manager: Arc<Mutex<CursorManager>>,
|
2019-02-21 10:51:43 +01:00
|
|
|
) -> WlPointer {
|
2018-10-15 07:15:43 +08:00
|
|
|
seat.get_pointer(|pointer| {
|
2020-01-11 11:45:52 +03:00
|
|
|
// Currently focused winit surface
|
2019-07-03 11:18:42 -07:00
|
|
|
let mut mouse_focus = None;
|
|
|
|
|
let mut axis_buffer = None;
|
|
|
|
|
let mut axis_discrete_buffer = None;
|
|
|
|
|
let mut axis_state = TouchPhase::Ended;
|
|
|
|
|
|
2019-06-21 11:33:15 -04:00
|
|
|
pointer.implement_closure(
|
|
|
|
|
move |evt, pointer| {
|
|
|
|
|
let store = store.lock().unwrap();
|
2019-10-03 16:02:59 +03:00
|
|
|
let mut cursor_manager = cursor_manager.lock().unwrap();
|
2019-06-21 11:33:15 -04:00
|
|
|
match evt {
|
|
|
|
|
PtrEvent::Enter {
|
|
|
|
|
surface,
|
|
|
|
|
surface_x,
|
|
|
|
|
surface_y,
|
|
|
|
|
..
|
|
|
|
|
} => {
|
|
|
|
|
let wid = store.find_wid(&surface);
|
2020-01-11 11:45:52 +03:00
|
|
|
|
2019-06-21 11:33:15 -04:00
|
|
|
if let Some(wid) = wid {
|
2020-01-11 11:45:52 +03:00
|
|
|
let scale_factor = surface::get_dpi_factor(&surface) as f64;
|
|
|
|
|
mouse_focus = Some(surface);
|
2019-12-18 16:41:44 +03:00
|
|
|
|
|
|
|
|
// Reload cursor style only when we enter winit's surface. Calling
|
|
|
|
|
// this function every time on `PtrEvent::Enter` could interfere with
|
|
|
|
|
// SCTK CSD handling, since it changes cursor icons when you hover
|
|
|
|
|
// cursor over the window borders.
|
|
|
|
|
cursor_manager.reload_cursor_style();
|
|
|
|
|
|
2019-06-25 12:00:41 +03:00
|
|
|
sink.send_window_event(
|
2019-06-21 11:33:15 -04:00
|
|
|
WindowEvent::CursorEntered {
|
|
|
|
|
device_id: crate::event::DeviceId(
|
|
|
|
|
crate::platform_impl::DeviceId::Wayland(DeviceId),
|
|
|
|
|
),
|
|
|
|
|
},
|
|
|
|
|
wid,
|
|
|
|
|
);
|
2019-06-25 12:00:41 +03:00
|
|
|
sink.send_window_event(
|
2019-06-21 11:33:15 -04:00
|
|
|
WindowEvent::CursorMoved {
|
|
|
|
|
device_id: crate::event::DeviceId(
|
|
|
|
|
crate::platform_impl::DeviceId::Wayland(DeviceId),
|
|
|
|
|
),
|
2020-01-11 11:45:52 +03:00
|
|
|
position: (surface_x * scale_factor, surface_y * scale_factor)
|
|
|
|
|
.into(),
|
2018-10-18 10:34:02 +08:00
|
|
|
modifiers: modifiers_tracker.lock().unwrap().clone(),
|
2018-10-15 07:15:43 +08:00
|
|
|
},
|
|
|
|
|
wid,
|
|
|
|
|
);
|
|
|
|
|
}
|
2019-06-24 12:14:55 -04:00
|
|
|
}
|
2019-06-21 11:33:15 -04:00
|
|
|
PtrEvent::Leave { surface, .. } => {
|
|
|
|
|
mouse_focus = None;
|
|
|
|
|
let wid = store.find_wid(&surface);
|
|
|
|
|
if let Some(wid) = wid {
|
2019-06-25 12:00:41 +03:00
|
|
|
sink.send_window_event(
|
2019-06-21 11:33:15 -04:00
|
|
|
WindowEvent::CursorLeft {
|
|
|
|
|
device_id: crate::event::DeviceId(
|
|
|
|
|
crate::platform_impl::DeviceId::Wayland(DeviceId),
|
|
|
|
|
),
|
|
|
|
|
},
|
|
|
|
|
wid,
|
|
|
|
|
);
|
|
|
|
|
}
|
2019-06-24 12:14:55 -04:00
|
|
|
}
|
2019-06-21 11:33:15 -04:00
|
|
|
PtrEvent::Motion {
|
|
|
|
|
surface_x,
|
|
|
|
|
surface_y,
|
|
|
|
|
..
|
|
|
|
|
} => {
|
2020-01-11 11:45:52 +03:00
|
|
|
if let Some(surface) = mouse_focus.as_ref() {
|
|
|
|
|
let scale_factor = surface::get_dpi_factor(&surface) as f64;
|
|
|
|
|
let wid = make_wid(surface);
|
2019-06-25 12:00:41 +03:00
|
|
|
sink.send_window_event(
|
2019-06-21 11:33:15 -04:00
|
|
|
WindowEvent::CursorMoved {
|
|
|
|
|
device_id: crate::event::DeviceId(
|
|
|
|
|
crate::platform_impl::DeviceId::Wayland(DeviceId),
|
|
|
|
|
),
|
2020-01-11 11:45:52 +03:00
|
|
|
position: (surface_x * scale_factor, surface_y * scale_factor)
|
|
|
|
|
.into(),
|
2018-10-18 10:34:02 +08:00
|
|
|
modifiers: modifiers_tracker.lock().unwrap().clone(),
|
2018-10-15 07:15:43 +08:00
|
|
|
},
|
|
|
|
|
wid,
|
|
|
|
|
);
|
2019-06-21 11:33:15 -04:00
|
|
|
}
|
2019-06-24 12:14:55 -04:00
|
|
|
}
|
2019-06-21 11:33:15 -04:00
|
|
|
PtrEvent::Button { button, state, .. } => {
|
2020-01-11 11:45:52 +03:00
|
|
|
if let Some(surface) = mouse_focus.as_ref() {
|
2019-06-21 11:33:15 -04:00
|
|
|
let state = match state {
|
|
|
|
|
wl_pointer::ButtonState::Pressed => ElementState::Pressed,
|
|
|
|
|
wl_pointer::ButtonState::Released => ElementState::Released,
|
|
|
|
|
_ => unreachable!(),
|
|
|
|
|
};
|
|
|
|
|
let button = match button {
|
|
|
|
|
0x110 => MouseButton::Left,
|
|
|
|
|
0x111 => MouseButton::Right,
|
|
|
|
|
0x112 => MouseButton::Middle,
|
|
|
|
|
// TODO figure out the translation ?
|
|
|
|
|
_ => return,
|
|
|
|
|
};
|
2019-06-25 12:00:41 +03:00
|
|
|
sink.send_window_event(
|
2019-06-21 11:33:15 -04:00
|
|
|
WindowEvent::MouseInput {
|
|
|
|
|
device_id: crate::event::DeviceId(
|
|
|
|
|
crate::platform_impl::DeviceId::Wayland(DeviceId),
|
|
|
|
|
),
|
|
|
|
|
state,
|
|
|
|
|
button,
|
2018-10-18 10:34:02 +08:00
|
|
|
modifiers: modifiers_tracker.lock().unwrap().clone(),
|
2018-10-15 07:15:43 +08:00
|
|
|
},
|
2020-01-11 11:45:52 +03:00
|
|
|
make_wid(surface),
|
2018-10-15 07:15:43 +08:00
|
|
|
);
|
|
|
|
|
}
|
2019-06-24 12:14:55 -04:00
|
|
|
}
|
2019-06-21 11:33:15 -04:00
|
|
|
PtrEvent::Axis { axis, value, .. } => {
|
2020-01-11 11:45:52 +03:00
|
|
|
if let Some(surface) = mouse_focus.as_ref() {
|
|
|
|
|
let wid = make_wid(surface);
|
2019-06-21 11:33:15 -04:00
|
|
|
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!(),
|
|
|
|
|
}
|
2019-06-25 12:00:41 +03:00
|
|
|
sink.send_window_event(
|
2019-06-21 11:33:15 -04:00
|
|
|
WindowEvent::MouseWheel {
|
|
|
|
|
device_id: crate::event::DeviceId(
|
|
|
|
|
crate::platform_impl::DeviceId::Wayland(DeviceId),
|
|
|
|
|
),
|
|
|
|
|
delta: MouseScrollDelta::PixelDelta(
|
|
|
|
|
(x as f64, y as f64).into(),
|
|
|
|
|
),
|
|
|
|
|
phase: TouchPhase::Moved,
|
|
|
|
|
modifiers: modifiers_tracker.lock().unwrap().clone(),
|
|
|
|
|
},
|
|
|
|
|
wid,
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
let (mut x, mut y) = 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!(),
|
|
|
|
|
}
|
|
|
|
|
axis_buffer = Some((x, y));
|
|
|
|
|
axis_state = match axis_state {
|
|
|
|
|
TouchPhase::Started | TouchPhase::Moved => TouchPhase::Moved,
|
|
|
|
|
_ => TouchPhase::Started,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-06-24 12:14:55 -04:00
|
|
|
}
|
2019-06-21 11:33:15 -04:00
|
|
|
PtrEvent::Frame => {
|
|
|
|
|
let axis_buffer = axis_buffer.take();
|
|
|
|
|
let axis_discrete_buffer = axis_discrete_buffer.take();
|
2020-01-11 11:45:52 +03:00
|
|
|
if let Some(surface) = mouse_focus.as_ref() {
|
|
|
|
|
let wid = make_wid(surface);
|
2019-06-21 11:33:15 -04:00
|
|
|
if let Some((x, y)) = axis_discrete_buffer {
|
2019-06-25 12:00:41 +03:00
|
|
|
sink.send_window_event(
|
2019-06-21 11:33:15 -04:00
|
|
|
WindowEvent::MouseWheel {
|
|
|
|
|
device_id: crate::event::DeviceId(
|
|
|
|
|
crate::platform_impl::DeviceId::Wayland(DeviceId),
|
|
|
|
|
),
|
|
|
|
|
delta: MouseScrollDelta::LineDelta(x as f32, y as f32),
|
|
|
|
|
phase: axis_state,
|
|
|
|
|
modifiers: modifiers_tracker.lock().unwrap().clone(),
|
|
|
|
|
},
|
|
|
|
|
wid,
|
|
|
|
|
);
|
|
|
|
|
} else if let Some((x, y)) = axis_buffer {
|
2019-06-25 12:00:41 +03:00
|
|
|
sink.send_window_event(
|
2019-06-21 11:33:15 -04:00
|
|
|
WindowEvent::MouseWheel {
|
|
|
|
|
device_id: crate::event::DeviceId(
|
|
|
|
|
crate::platform_impl::DeviceId::Wayland(DeviceId),
|
|
|
|
|
),
|
|
|
|
|
delta: MouseScrollDelta::PixelDelta(
|
|
|
|
|
(x as f64, y as f64).into(),
|
|
|
|
|
),
|
|
|
|
|
phase: axis_state,
|
|
|
|
|
modifiers: modifiers_tracker.lock().unwrap().clone(),
|
|
|
|
|
},
|
|
|
|
|
wid,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-06-24 12:14:55 -04:00
|
|
|
}
|
2019-06-21 11:33:15 -04:00
|
|
|
PtrEvent::AxisSource { .. } => (),
|
|
|
|
|
PtrEvent::AxisStop { .. } => {
|
|
|
|
|
axis_state = TouchPhase::Ended;
|
2019-06-24 12:14:55 -04:00
|
|
|
}
|
2019-06-21 11:33:15 -04:00
|
|
|
PtrEvent::AxisDiscrete { axis, discrete } => {
|
|
|
|
|
let (mut x, mut y) = axis_discrete_buffer.unwrap_or((0, 0));
|
|
|
|
|
match axis {
|
|
|
|
|
// wayland vertical sign convention is the inverse of winit
|
|
|
|
|
wl_pointer::Axis::VerticalScroll => y -= discrete,
|
|
|
|
|
wl_pointer::Axis::HorizontalScroll => x += discrete,
|
|
|
|
|
_ => unreachable!(),
|
|
|
|
|
}
|
|
|
|
|
axis_discrete_buffer = Some((x, y));
|
|
|
|
|
axis_state = match axis_state {
|
|
|
|
|
TouchPhase::Started | TouchPhase::Moved => TouchPhase::Moved,
|
|
|
|
|
_ => TouchPhase::Started,
|
|
|
|
|
}
|
2019-06-24 12:14:55 -04:00
|
|
|
}
|
2019-06-21 11:33:15 -04:00
|
|
|
_ => unreachable!(),
|
2018-10-15 07:15:43 +08:00
|
|
|
}
|
2019-06-21 11:33:15 -04:00
|
|
|
},
|
|
|
|
|
(),
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
.unwrap()
|
2017-11-12 13:56:57 -07:00
|
|
|
}
|
2019-06-25 12:00:41 +03:00
|
|
|
|
2020-01-04 01:31:23 -05:00
|
|
|
pub fn implement_relative_pointer(
|
|
|
|
|
sink: EventsSink,
|
2019-06-25 12:00:41 +03:00
|
|
|
pointer: &WlPointer,
|
|
|
|
|
manager: &ZwpRelativePointerManagerV1,
|
|
|
|
|
) -> Result<ZwpRelativePointerV1, ()> {
|
|
|
|
|
manager.get_relative_pointer(pointer, |rel_pointer| {
|
|
|
|
|
rel_pointer.implement_closure(
|
2020-01-04 01:31:23 -05:00
|
|
|
move |evt, _rel_pointer| match evt {
|
|
|
|
|
Event::RelativeMotion { dx, dy, .. } => {
|
|
|
|
|
sink.send_device_event(DeviceEvent::MouseMotion { delta: (dx, dy) }, DeviceId)
|
2019-06-25 12:00:41 +03:00
|
|
|
}
|
2020-01-04 01:31:23 -05:00
|
|
|
_ => unreachable!(),
|
2019-06-25 12:00:41 +03:00
|
|
|
},
|
|
|
|
|
(),
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
}
|
2019-10-02 03:25:59 +02:00
|
|
|
|
|
|
|
|
pub fn implement_locked_pointer(
|
|
|
|
|
surface: &WlSurface,
|
|
|
|
|
pointer: &WlPointer,
|
|
|
|
|
constraints: &ZwpPointerConstraintsV1,
|
|
|
|
|
) -> Result<ZwpLockedPointerV1, ()> {
|
|
|
|
|
constraints.lock_pointer(surface, pointer, None, Lifetime::Persistent.to_raw(), |c| {
|
|
|
|
|
c.implement_closure(|_, _| (), ())
|
|
|
|
|
})
|
|
|
|
|
}
|