2017-11-11 10:03:42 +01:00
|
|
|
use std::sync::{Arc, Mutex};
|
|
|
|
|
|
2018-05-05 19:36:34 +02:00
|
|
|
use {ElementState, MouseButton, MouseScrollDelta, TouchPhase, WindowEvent};
|
2017-12-26 16:46:28 -05:00
|
|
|
use events::ModifiersState;
|
2017-11-11 10:03:42 +01:00
|
|
|
|
2018-05-05 19:36:34 +02:00
|
|
|
use super::DeviceId;
|
2019-02-05 10:30:33 -05:00
|
|
|
use super::event_loop::EventLoopSink;
|
2017-11-11 10:03:42 +01:00
|
|
|
use super::window::WindowStore;
|
|
|
|
|
|
2018-10-15 07:15:43 +08:00
|
|
|
use sctk::reexports::client::Proxy;
|
2018-05-05 19:36:34 +02:00
|
|
|
use sctk::reexports::client::protocol::wl_pointer::{self, Event as PtrEvent, WlPointer};
|
2018-10-15 07:15:43 +08:00
|
|
|
use sctk::reexports::client::protocol::wl_seat;
|
|
|
|
|
use sctk::reexports::client::protocol::wl_seat::RequestsTrait as SeatRequests;
|
2017-11-11 10:03:42 +01:00
|
|
|
|
2018-05-05 19:36:34 +02:00
|
|
|
pub fn implement_pointer(
|
2018-10-15 07:15:43 +08:00
|
|
|
seat: &Proxy<wl_seat::WlSeat>,
|
2019-02-05 10:30:33 -05:00
|
|
|
sink: Arc<Mutex<EventLoopSink>>,
|
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>>,
|
2018-05-05 19:36:34 +02:00
|
|
|
) -> Proxy<WlPointer> {
|
|
|
|
|
let mut mouse_focus = None;
|
|
|
|
|
let mut axis_buffer = None;
|
|
|
|
|
let mut axis_discrete_buffer = None;
|
|
|
|
|
let mut axis_state = TouchPhase::Ended;
|
2017-11-11 10:03:42 +01:00
|
|
|
|
2018-10-15 07:15:43 +08:00
|
|
|
seat.get_pointer(|pointer| {
|
|
|
|
|
pointer.implement(move |evt, pointer| {
|
|
|
|
|
let mut sink = sink.lock().unwrap();
|
|
|
|
|
let store = store.lock().unwrap();
|
|
|
|
|
match evt {
|
|
|
|
|
PtrEvent::Enter {
|
|
|
|
|
surface,
|
|
|
|
|
surface_x,
|
|
|
|
|
surface_y,
|
|
|
|
|
..
|
|
|
|
|
} => {
|
|
|
|
|
let wid = store.find_wid(&surface);
|
|
|
|
|
if let Some(wid) = wid {
|
|
|
|
|
mouse_focus = Some(wid);
|
2018-05-05 19:36:34 +02:00
|
|
|
sink.send_event(
|
2018-10-15 07:15:43 +08:00
|
|
|
WindowEvent::CursorEntered {
|
2018-05-05 19:36:34 +02:00
|
|
|
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
|
2018-10-15 07:15:43 +08:00
|
|
|
},
|
|
|
|
|
wid,
|
|
|
|
|
);
|
|
|
|
|
sink.send_event(
|
|
|
|
|
WindowEvent::CursorMoved {
|
|
|
|
|
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
|
|
|
|
|
position: (surface_x, surface_y).into(),
|
2018-10-18 10:34:02 +08:00
|
|
|
modifiers: modifiers_tracker.lock().unwrap().clone(),
|
2018-05-05 19:36:34 +02:00
|
|
|
},
|
|
|
|
|
wid,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-10-15 07:15:43 +08:00
|
|
|
PtrEvent::Leave { surface, .. } => {
|
|
|
|
|
mouse_focus = None;
|
|
|
|
|
let wid = store.find_wid(&surface);
|
|
|
|
|
if let Some(wid) = wid {
|
|
|
|
|
sink.send_event(
|
|
|
|
|
WindowEvent::CursorLeft {
|
|
|
|
|
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
|
|
|
|
|
},
|
|
|
|
|
wid,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
PtrEvent::Motion {
|
|
|
|
|
surface_x,
|
|
|
|
|
surface_y,
|
|
|
|
|
..
|
|
|
|
|
} => {
|
|
|
|
|
if let Some(wid) = mouse_focus {
|
2018-05-05 19:36:34 +02:00
|
|
|
sink.send_event(
|
2018-10-15 07:15:43 +08:00
|
|
|
WindowEvent::CursorMoved {
|
2018-05-05 19:36:34 +02:00
|
|
|
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
|
2018-10-15 07:15:43 +08:00
|
|
|
position: (surface_x, surface_y).into(),
|
2018-10-18 10:34:02 +08:00
|
|
|
modifiers: modifiers_tracker.lock().unwrap().clone(),
|
2018-05-05 19:36:34 +02:00
|
|
|
},
|
|
|
|
|
wid,
|
|
|
|
|
);
|
2018-10-15 07:15:43 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
PtrEvent::Button { button, state, .. } => {
|
|
|
|
|
if let Some(wid) = mouse_focus {
|
|
|
|
|
let state = match state {
|
|
|
|
|
wl_pointer::ButtonState::Pressed => ElementState::Pressed,
|
|
|
|
|
wl_pointer::ButtonState::Released => ElementState::Released,
|
|
|
|
|
};
|
|
|
|
|
let button = match button {
|
|
|
|
|
0x110 => MouseButton::Left,
|
|
|
|
|
0x111 => MouseButton::Right,
|
|
|
|
|
0x112 => MouseButton::Middle,
|
|
|
|
|
// TODO figure out the translation ?
|
|
|
|
|
_ => return,
|
|
|
|
|
};
|
2018-05-05 19:36:34 +02:00
|
|
|
sink.send_event(
|
2018-10-15 07:15:43 +08:00
|
|
|
WindowEvent::MouseInput {
|
2018-05-05 19:36:34 +02:00
|
|
|
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
|
2018-10-15 07:15:43 +08:00
|
|
|
state: state,
|
|
|
|
|
button: button,
|
2018-10-18 10:34:02 +08:00
|
|
|
modifiers: modifiers_tracker.lock().unwrap().clone(),
|
2018-05-05 19:36:34 +02:00
|
|
|
},
|
|
|
|
|
wid,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-10-15 07:15:43 +08:00
|
|
|
PtrEvent::Axis { axis, value, .. } => {
|
|
|
|
|
if let Some(wid) = mouse_focus {
|
|
|
|
|
if pointer.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,
|
|
|
|
|
}
|
|
|
|
|
sink.send_event(
|
|
|
|
|
WindowEvent::MouseWheel {
|
|
|
|
|
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
|
|
|
|
|
delta: MouseScrollDelta::PixelDelta((x as f64, y as f64).into()),
|
|
|
|
|
phase: TouchPhase::Moved,
|
2018-10-18 10:34:02 +08:00
|
|
|
modifiers: modifiers_tracker.lock().unwrap().clone(),
|
2018-10-15 07:15:43 +08:00
|
|
|
},
|
|
|
|
|
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,
|
|
|
|
|
}
|
|
|
|
|
axis_buffer = Some((x, y));
|
|
|
|
|
axis_state = match axis_state {
|
|
|
|
|
TouchPhase::Started | TouchPhase::Moved => TouchPhase::Moved,
|
|
|
|
|
_ => TouchPhase::Started,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-05-05 19:36:34 +02:00
|
|
|
}
|
2018-10-15 07:15:43 +08:00
|
|
|
PtrEvent::Frame => {
|
|
|
|
|
let axis_buffer = axis_buffer.take();
|
|
|
|
|
let axis_discrete_buffer = axis_discrete_buffer.take();
|
|
|
|
|
if let Some(wid) = mouse_focus {
|
|
|
|
|
if let Some((x, y)) = axis_discrete_buffer {
|
|
|
|
|
sink.send_event(
|
|
|
|
|
WindowEvent::MouseWheel {
|
|
|
|
|
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
|
|
|
|
|
delta: MouseScrollDelta::LineDelta(x as f32, y as f32),
|
|
|
|
|
phase: axis_state,
|
2018-10-18 10:34:02 +08:00
|
|
|
modifiers: modifiers_tracker.lock().unwrap().clone(),
|
2018-10-15 07:15:43 +08:00
|
|
|
},
|
|
|
|
|
wid,
|
|
|
|
|
);
|
|
|
|
|
} else if let Some((x, y)) = axis_buffer {
|
|
|
|
|
sink.send_event(
|
|
|
|
|
WindowEvent::MouseWheel {
|
|
|
|
|
device_id: ::DeviceId(::platform::DeviceId::Wayland(DeviceId)),
|
|
|
|
|
delta: MouseScrollDelta::PixelDelta((x as f64, y as f64).into()),
|
|
|
|
|
phase: axis_state,
|
2018-10-18 10:34:02 +08:00
|
|
|
modifiers: modifiers_tracker.lock().unwrap().clone(),
|
2018-10-15 07:15:43 +08:00
|
|
|
},
|
|
|
|
|
wid,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
PtrEvent::AxisSource { .. } => (),
|
|
|
|
|
PtrEvent::AxisStop { .. } => {
|
|
|
|
|
axis_state = TouchPhase::Ended;
|
|
|
|
|
}
|
|
|
|
|
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,
|
|
|
|
|
}
|
|
|
|
|
axis_discrete_buffer = Some((x, y));
|
|
|
|
|
axis_state = match axis_state {
|
|
|
|
|
TouchPhase::Started | TouchPhase::Moved => TouchPhase::Moved,
|
|
|
|
|
_ => TouchPhase::Started,
|
|
|
|
|
}
|
2018-05-05 19:36:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
2018-10-15 07:15:43 +08:00
|
|
|
}, ())
|
|
|
|
|
}).unwrap()
|
2017-11-12 13:56:57 -07:00
|
|
|
}
|