mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-25 06:41:31 +11:00
wayland: move input logic to the event loop
This commit is contained in:
parent
7336cacf07
commit
17fde48ed7
|
@ -1,18 +1,11 @@
|
||||||
use {WindowEvent as Event, ElementState, MouseButton, MouseScrollDelta, TouchPhase};
|
|
||||||
|
|
||||||
use events::ModifiersState;
|
|
||||||
|
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use wayland_client::{EnvHandler, default_connect, EventQueue, EventQueueHandle, Init, Proxy};
|
use wayland_client::{EnvHandler, default_connect, EventQueue, EventQueueHandle, Init, Proxy};
|
||||||
use wayland_client::protocol::{wl_compositor, wl_seat, wl_shell, wl_shm, wl_subcompositor,
|
use wayland_client::protocol::{wl_compositor, wl_seat, wl_shell, wl_shm, wl_subcompositor,
|
||||||
wl_display, wl_registry, wl_output, wl_surface, wl_pointer,
|
wl_display, wl_registry, wl_output, wl_surface};
|
||||||
wl_keyboard};
|
|
||||||
|
|
||||||
use super::{wayland_window, EventsLoopSink, make_wid};
|
use super::wayland_window;
|
||||||
use super::wayland_kbd::MappedKeyboard;
|
|
||||||
use super::keyboard::KbdHandler;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Registry and globals handling
|
* Registry and globals handling
|
||||||
|
@ -25,26 +18,11 @@ wayland_env!(InnerEnv,
|
||||||
subcompositor: wl_subcompositor::WlSubcompositor
|
subcompositor: wl_subcompositor::WlSubcompositor
|
||||||
);
|
);
|
||||||
|
|
||||||
enum KbdType {
|
|
||||||
Mapped(MappedKeyboard<KbdHandler>),
|
|
||||||
Plain(Option<(Arc<wl_surface::WlSurface>,Arc<Mutex<EventsLoopSink>>)>)
|
|
||||||
}
|
|
||||||
|
|
||||||
struct WaylandEnv {
|
struct WaylandEnv {
|
||||||
registry: wl_registry::WlRegistry,
|
registry: wl_registry::WlRegistry,
|
||||||
inner: EnvHandler<InnerEnv>,
|
inner: EnvHandler<InnerEnv>,
|
||||||
monitors: Vec<OutputInfo>,
|
monitors: Vec<OutputInfo>,
|
||||||
my_id: usize,
|
my_id: usize,
|
||||||
windows: Vec<(Arc<wl_surface::WlSurface>,Arc<Mutex<EventsLoopSink>>)>,
|
|
||||||
seat: Option<wl_seat::WlSeat>,
|
|
||||||
mouse: Option<wl_pointer::WlPointer>,
|
|
||||||
mouse_focus: Option<(Arc<wl_surface::WlSurface>,Arc<Mutex<EventsLoopSink>>)>,
|
|
||||||
mouse_location: (i32, i32),
|
|
||||||
axis_buffer: Option<(f32, f32)>,
|
|
||||||
axis_discrete_buffer: Option<(i32, i32)>,
|
|
||||||
axis_state: TouchPhase,
|
|
||||||
kbd: Option<wl_keyboard::WlKeyboard>,
|
|
||||||
kbd_handler: KbdType
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct OutputInfo {
|
struct OutputInfo {
|
||||||
|
@ -69,25 +47,11 @@ impl OutputInfo {
|
||||||
|
|
||||||
impl WaylandEnv {
|
impl WaylandEnv {
|
||||||
fn new(registry: wl_registry::WlRegistry) -> WaylandEnv {
|
fn new(registry: wl_registry::WlRegistry) -> WaylandEnv {
|
||||||
let kbd_handler = match MappedKeyboard::new(KbdHandler::new()) {
|
|
||||||
Ok(h) => KbdType::Mapped(h),
|
|
||||||
Err(_) => KbdType::Plain(None)
|
|
||||||
};
|
|
||||||
WaylandEnv {
|
WaylandEnv {
|
||||||
registry: registry,
|
registry: registry,
|
||||||
inner: EnvHandler::new(),
|
inner: EnvHandler::new(),
|
||||||
monitors: Vec::new(),
|
monitors: Vec::new(),
|
||||||
my_id: 0,
|
my_id: 0,
|
||||||
windows: Vec::new(),
|
|
||||||
seat: None,
|
|
||||||
mouse: None,
|
|
||||||
mouse_focus: None,
|
|
||||||
mouse_location: (0,0),
|
|
||||||
axis_buffer: None,
|
|
||||||
axis_discrete_buffer: None,
|
|
||||||
axis_state: TouchPhase::Started,
|
|
||||||
kbd: None,
|
|
||||||
kbd_handler: kbd_handler
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,14 +91,6 @@ impl wl_registry::Handler for WaylandEnv {
|
||||||
.expect("Registry cannot be dead");
|
.expect("Registry cannot be dead");
|
||||||
evqh.register::<_, WaylandEnv>(&output, self.my_id);
|
evqh.register::<_, WaylandEnv>(&output, self.my_id);
|
||||||
self.monitors.push(OutputInfo::new(output, name));
|
self.monitors.push(OutputInfo::new(output, name));
|
||||||
} else if interface == "wl_seat" && self.seat.is_none() {
|
|
||||||
// Only grab the first seat
|
|
||||||
// TODO: Handle multi-seat-setup?
|
|
||||||
assert!(version >= 5, "Version 5 of seat interface is needed by glutin.");
|
|
||||||
let seat = self.registry.bind::<wl_seat::WlSeat>(5, name)
|
|
||||||
.expect("Registry cannot be dead");
|
|
||||||
evqh.register::<_, WaylandEnv>(&seat, self.my_id);
|
|
||||||
self.seat = Some(seat);
|
|
||||||
}
|
}
|
||||||
self.inner.global(evqh, registry, name, interface, version);
|
self.inner.global(evqh, registry, name, interface, version);
|
||||||
}
|
}
|
||||||
|
@ -242,6 +198,12 @@ impl WaylandContext {
|
||||||
let _ = self.display.flush();
|
let _ = self.display.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_seat(&self) -> Option<wl_seat::WlSeat> {
|
||||||
|
let mut guard = self.evq.lock().unwrap();
|
||||||
|
let state = guard.state();
|
||||||
|
state.get_handler::<WaylandEnv>(self.env_id).get_seat()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn with_output<F>(&self, id: MonitorId, f: F) where F: FnOnce(&wl_output::WlOutput) {
|
pub fn with_output<F>(&self, id: MonitorId, f: F) where F: FnOnce(&wl_output::WlOutput) {
|
||||||
let mut guard = self.evq.lock().unwrap();
|
let mut guard = self.evq.lock().unwrap();
|
||||||
let state = guard.state();
|
let state = guard.state();
|
||||||
|
@ -252,7 +214,7 @@ impl WaylandContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_window<H: wayland_window::Handler>(&self, sink: Arc<Mutex<EventsLoopSink>>)
|
pub fn create_window<H: wayland_window::Handler>(&self)
|
||||||
-> (Arc<wl_surface::WlSurface>, wayland_window::DecoratedSurface<H>)
|
-> (Arc<wl_surface::WlSurface>, wayland_window::DecoratedSurface<H>)
|
||||||
{
|
{
|
||||||
let mut guard = self.evq.lock().unwrap();
|
let mut guard = self.evq.lock().unwrap();
|
||||||
|
@ -260,7 +222,6 @@ impl WaylandContext {
|
||||||
let env = state.get_mut_handler::<WaylandEnv>(self.env_id);
|
let env = state.get_mut_handler::<WaylandEnv>(self.env_id);
|
||||||
// this "expect" cannot trigger (see https://github.com/vberger/wayland-client-rs/issues/69)
|
// this "expect" cannot trigger (see https://github.com/vberger/wayland-client-rs/issues/69)
|
||||||
let surface = Arc::new(env.inner.compositor.create_surface().expect("Compositor cannot be dead"));
|
let surface = Arc::new(env.inner.compositor.create_surface().expect("Compositor cannot be dead"));
|
||||||
env.windows.push((surface.clone(), sink));
|
|
||||||
let decorated = wayland_window::DecoratedSurface::new(
|
let decorated = wayland_window::DecoratedSurface::new(
|
||||||
&*surface, 800, 600,
|
&*surface, 800, 600,
|
||||||
&env.inner.compositor,
|
&env.inner.compositor,
|
||||||
|
@ -272,13 +233,6 @@ impl WaylandContext {
|
||||||
).expect("Failed to create a tmpfile buffer.");
|
).expect("Failed to create a tmpfile buffer.");
|
||||||
(surface, decorated)
|
(surface, decorated)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prune_dead_windows(&self) {
|
|
||||||
let mut guard = self.evq.lock().unwrap();
|
|
||||||
let mut state = guard.state();
|
|
||||||
let env = state.get_mut_handler::<WaylandEnv>(self.env_id);
|
|
||||||
env.windows.retain(|w| w.0.is_alive());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -342,346 +296,3 @@ impl MonitorId {
|
||||||
(0,0)
|
(0,0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Input Handling
|
|
||||||
*/
|
|
||||||
|
|
||||||
impl wl_seat::Handler for WaylandEnv {
|
|
||||||
fn capabilities(&mut self,
|
|
||||||
evqh: &mut EventQueueHandle,
|
|
||||||
seat: &wl_seat::WlSeat,
|
|
||||||
capabilities: wl_seat::Capability)
|
|
||||||
{
|
|
||||||
// create pointer if applicable
|
|
||||||
if capabilities.contains(wl_seat::Pointer) && self.mouse.is_none() {
|
|
||||||
let pointer = seat.get_pointer().expect("Seat is not dead");
|
|
||||||
evqh.register::<_, WaylandEnv>(&pointer, self.my_id);
|
|
||||||
self.mouse = Some(pointer);
|
|
||||||
}
|
|
||||||
// destroy pointer if applicable
|
|
||||||
if !capabilities.contains(wl_seat::Pointer) {
|
|
||||||
if let Some(pointer) = self.mouse.take() {
|
|
||||||
pointer.release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// create keyboard if applicable
|
|
||||||
if capabilities.contains(wl_seat::Keyboard) && self.kbd.is_none() {
|
|
||||||
let kbd = seat.get_keyboard().expect("Seat is not dead");
|
|
||||||
evqh.register::<_, WaylandEnv>(&kbd, self.my_id);
|
|
||||||
self.kbd = Some(kbd);
|
|
||||||
}
|
|
||||||
// destroy keyboard if applicable
|
|
||||||
if !capabilities.contains(wl_seat::Keyboard) {
|
|
||||||
if let Some(kbd) = self.kbd.take() {
|
|
||||||
kbd.release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
declare_handler!(WaylandEnv, wl_seat::Handler, wl_seat::WlSeat);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Pointer Handling
|
|
||||||
*/
|
|
||||||
|
|
||||||
impl wl_pointer::Handler for WaylandEnv {
|
|
||||||
fn enter(&mut self,
|
|
||||||
_evqh: &mut EventQueueHandle,
|
|
||||||
_proxy: &wl_pointer::WlPointer,
|
|
||||||
_serial: u32,
|
|
||||||
surface: &wl_surface::WlSurface,
|
|
||||||
surface_x: f64,
|
|
||||||
surface_y: f64)
|
|
||||||
{
|
|
||||||
self.mouse_location = (surface_x as i32, surface_y as i32);
|
|
||||||
for &(ref window, ref sink) in &self.windows {
|
|
||||||
if window.equals(surface) {
|
|
||||||
self.mouse_focus = Some((window.clone(), sink.clone()));
|
|
||||||
let (w, h) = self.mouse_location;
|
|
||||||
let mut event_queue = sink.lock().unwrap();
|
|
||||||
event_queue.push_event(Event::MouseEntered, make_wid(window));
|
|
||||||
event_queue.push_event(Event::MouseMoved(w, h), make_wid(window));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn leave(&mut self,
|
|
||||||
_evqh: &mut EventQueueHandle,
|
|
||||||
_proxy: &wl_pointer::WlPointer,
|
|
||||||
_serial: u32,
|
|
||||||
surface: &wl_surface::WlSurface)
|
|
||||||
{
|
|
||||||
self.mouse_focus = None;
|
|
||||||
for &(ref window, ref sink) in &self.windows {
|
|
||||||
if window.equals(surface) {
|
|
||||||
let mut event_queue = sink.lock().unwrap();
|
|
||||||
event_queue.push_event(Event::MouseLeft, make_wid(window));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn motion(&mut self,
|
|
||||||
_evqh: &mut EventQueueHandle,
|
|
||||||
_proxy: &wl_pointer::WlPointer,
|
|
||||||
_time: u32,
|
|
||||||
surface_x: f64,
|
|
||||||
surface_y: f64)
|
|
||||||
{
|
|
||||||
self.mouse_location = (surface_x as i32, surface_y as i32);
|
|
||||||
if let Some((ref window, ref sink)) = self.mouse_focus {
|
|
||||||
let (w,h) = self.mouse_location;
|
|
||||||
sink.lock().unwrap().push_event(
|
|
||||||
Event::MouseMoved(w, h),
|
|
||||||
make_wid(window)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn button(&mut self,
|
|
||||||
_evqh: &mut EventQueueHandle,
|
|
||||||
_proxy: &wl_pointer::WlPointer,
|
|
||||||
_serial: u32,
|
|
||||||
_time: u32,
|
|
||||||
button: u32,
|
|
||||||
state: wl_pointer::ButtonState)
|
|
||||||
{
|
|
||||||
if let Some((ref window, ref sink)) = self.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
|
|
||||||
};
|
|
||||||
sink.lock().unwrap().push_event(
|
|
||||||
Event::MouseInput(state, button),
|
|
||||||
make_wid(window)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn axis(&mut self,
|
|
||||||
_evqh: &mut EventQueueHandle,
|
|
||||||
_proxy: &wl_pointer::WlPointer,
|
|
||||||
_time: u32,
|
|
||||||
axis: wl_pointer::Axis,
|
|
||||||
value: f64)
|
|
||||||
{
|
|
||||||
let (mut x, mut y) = self.axis_buffer.unwrap_or((0.0, 0.0));
|
|
||||||
match axis {
|
|
||||||
wl_pointer::Axis::VerticalScroll => y += value as f32,
|
|
||||||
wl_pointer::Axis::HorizontalScroll => x += value as f32
|
|
||||||
}
|
|
||||||
self.axis_buffer = Some((x,y));
|
|
||||||
self.axis_state = match self.axis_state {
|
|
||||||
TouchPhase::Started | TouchPhase::Moved => TouchPhase::Moved,
|
|
||||||
_ => TouchPhase::Started
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn frame(&mut self,
|
|
||||||
_evqh: &mut EventQueueHandle,
|
|
||||||
_proxy: &wl_pointer::WlPointer)
|
|
||||||
{
|
|
||||||
let axis_buffer = self.axis_buffer.take();
|
|
||||||
let axis_discrete_buffer = self.axis_discrete_buffer.take();
|
|
||||||
if let Some((ref window, ref sink)) = self.mouse_focus {
|
|
||||||
if let Some((x, y)) = axis_discrete_buffer {
|
|
||||||
sink.lock().unwrap().push_event(
|
|
||||||
Event::MouseWheel(
|
|
||||||
MouseScrollDelta::LineDelta(x as f32, y as f32),
|
|
||||||
self.axis_state
|
|
||||||
),
|
|
||||||
make_wid(window)
|
|
||||||
);
|
|
||||||
} else if let Some((x, y)) = axis_buffer {
|
|
||||||
sink.lock().unwrap().push_event(
|
|
||||||
Event::MouseWheel(
|
|
||||||
MouseScrollDelta::PixelDelta(x as f32, y as f32),
|
|
||||||
self.axis_state
|
|
||||||
),
|
|
||||||
make_wid(window)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn axis_source(&mut self,
|
|
||||||
_evqh: &mut EventQueueHandle,
|
|
||||||
_proxy: &wl_pointer::WlPointer,
|
|
||||||
_axis_source: wl_pointer::AxisSource)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
fn axis_stop(&mut self,
|
|
||||||
_evqh: &mut EventQueueHandle,
|
|
||||||
_proxy: &wl_pointer::WlPointer,
|
|
||||||
_time: u32,
|
|
||||||
_axis: wl_pointer::Axis)
|
|
||||||
{
|
|
||||||
self.axis_state = TouchPhase::Ended;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn axis_discrete(&mut self,
|
|
||||||
_evqh: &mut EventQueueHandle,
|
|
||||||
_proxy: &wl_pointer::WlPointer,
|
|
||||||
axis: wl_pointer::Axis,
|
|
||||||
discrete: i32)
|
|
||||||
{
|
|
||||||
let (mut x, mut y) = self.axis_discrete_buffer.unwrap_or((0,0));
|
|
||||||
match axis {
|
|
||||||
wl_pointer::Axis::VerticalScroll => y += discrete,
|
|
||||||
wl_pointer::Axis::HorizontalScroll => x += discrete
|
|
||||||
}
|
|
||||||
self.axis_discrete_buffer = Some((x,y));
|
|
||||||
self.axis_state = match self.axis_state {
|
|
||||||
TouchPhase::Started | TouchPhase::Moved => TouchPhase::Moved,
|
|
||||||
_ => TouchPhase::Started
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
declare_handler!(WaylandEnv, wl_pointer::Handler, wl_pointer::WlPointer);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Keyboard Handling
|
|
||||||
*/
|
|
||||||
|
|
||||||
impl wl_keyboard::Handler for WaylandEnv {
|
|
||||||
// mostly pass-through
|
|
||||||
fn keymap(&mut self,
|
|
||||||
evqh: &mut EventQueueHandle,
|
|
||||||
proxy: &wl_keyboard::WlKeyboard,
|
|
||||||
format: wl_keyboard::KeymapFormat,
|
|
||||||
fd: ::std::os::unix::io::RawFd,
|
|
||||||
size: u32)
|
|
||||||
{
|
|
||||||
match self.kbd_handler {
|
|
||||||
KbdType::Mapped(ref mut h) => h.keymap(evqh, proxy, format, fd, size),
|
|
||||||
_ => ()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn enter(&mut self,
|
|
||||||
evqh: &mut EventQueueHandle,
|
|
||||||
proxy: &wl_keyboard::WlKeyboard,
|
|
||||||
serial: u32,
|
|
||||||
surface: &wl_surface::WlSurface,
|
|
||||||
keys: Vec<u8>)
|
|
||||||
{
|
|
||||||
let mut opt_sink = None;
|
|
||||||
for &(ref window, ref sink) in &self.windows {
|
|
||||||
if window.equals(surface) {
|
|
||||||
opt_sink = Some((window.clone(), sink.clone()));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some((ref window, ref sink)) = opt_sink {
|
|
||||||
// send focused event
|
|
||||||
let mut guard = sink.lock().unwrap();
|
|
||||||
guard.push_event(Event::Focused(true), make_wid(window));
|
|
||||||
}
|
|
||||||
match self.kbd_handler {
|
|
||||||
KbdType::Mapped(ref mut h) => {
|
|
||||||
h.handler().target = opt_sink;
|
|
||||||
h.enter(evqh, proxy, serial, surface, keys);
|
|
||||||
},
|
|
||||||
KbdType::Plain(ref mut opt) => { *opt = opt_sink; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn leave(&mut self,
|
|
||||||
evqh: &mut EventQueueHandle,
|
|
||||||
proxy: &wl_keyboard::WlKeyboard,
|
|
||||||
serial: u32,
|
|
||||||
surface: &wl_surface::WlSurface)
|
|
||||||
{
|
|
||||||
let opt_sink = match self.kbd_handler {
|
|
||||||
KbdType::Mapped(ref mut h) => {
|
|
||||||
let sink = h.handler().target.take();
|
|
||||||
h.leave(evqh, proxy, serial, surface);
|
|
||||||
sink
|
|
||||||
},
|
|
||||||
KbdType::Plain(ref mut opt) => opt.take()
|
|
||||||
};
|
|
||||||
if let Some((ref window, ref sink)) = opt_sink {
|
|
||||||
let mut guard = sink.lock().unwrap();
|
|
||||||
guard.push_event(Event::Focused(false), make_wid(window));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn key(&mut self,
|
|
||||||
evqh: &mut EventQueueHandle,
|
|
||||||
proxy: &wl_keyboard::WlKeyboard,
|
|
||||||
serial: u32,
|
|
||||||
time: u32,
|
|
||||||
key: u32,
|
|
||||||
state: wl_keyboard::KeyState)
|
|
||||||
{
|
|
||||||
match self.kbd_handler {
|
|
||||||
KbdType::Mapped(ref mut h) => h.key(evqh, proxy, serial, time, key, state),
|
|
||||||
KbdType::Plain(Some((ref window, ref sink))) => {
|
|
||||||
let state = match state {
|
|
||||||
wl_keyboard::KeyState::Pressed => ElementState::Pressed,
|
|
||||||
wl_keyboard::KeyState::Released => ElementState::Released,
|
|
||||||
};
|
|
||||||
let mut guard = sink.lock().unwrap();
|
|
||||||
// This is fallback impl if libxkbcommon was not available
|
|
||||||
// This case should probably never happen, as most wayland
|
|
||||||
// compositors _need_ libxkbcommon anyway...
|
|
||||||
//
|
|
||||||
// In this case, we don't have the modifiers state information
|
|
||||||
// anyway, as we need libxkbcommon to interpret it (it is
|
|
||||||
// supposed to be serialized by the compositor using libxkbcommon)
|
|
||||||
guard.push_event(
|
|
||||||
Event::KeyboardInput(
|
|
||||||
state,
|
|
||||||
key as u8,
|
|
||||||
None,
|
|
||||||
ModifiersState::default()
|
|
||||||
),
|
|
||||||
make_wid(window)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
KbdType::Plain(None) => ()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn modifiers(&mut self,
|
|
||||||
evqh: &mut EventQueueHandle,
|
|
||||||
proxy: &wl_keyboard::WlKeyboard,
|
|
||||||
serial: u32,
|
|
||||||
mods_depressed: u32,
|
|
||||||
mods_latched: u32,
|
|
||||||
mods_locked: u32,
|
|
||||||
group: u32)
|
|
||||||
{
|
|
||||||
match self.kbd_handler {
|
|
||||||
KbdType::Mapped(ref mut h) => h.modifiers(evqh, proxy, serial, mods_depressed,
|
|
||||||
mods_latched, mods_locked, group),
|
|
||||||
_ => ()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn repeat_info(&mut self,
|
|
||||||
evqh: &mut EventQueueHandle,
|
|
||||||
proxy: &wl_keyboard::WlKeyboard,
|
|
||||||
rate: i32,
|
|
||||||
delay: i32)
|
|
||||||
{
|
|
||||||
match self.kbd_handler {
|
|
||||||
KbdType::Mapped(ref mut h) => h.repeat_info(evqh, proxy, rate, delay),
|
|
||||||
_ => ()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
declare_handler!(WaylandEnv, wl_keyboard::Handler, wl_keyboard::WlKeyboard);
|
|
||||||
|
|
|
@ -1,15 +1,23 @@
|
||||||
|
use {WindowEvent as Event, ElementState, MouseButton, MouseScrollDelta, TouchPhase, ModifiersState};
|
||||||
|
|
||||||
|
use std::cell::UnsafeCell;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::sync::atomic::AtomicBool;
|
use std::sync::atomic::AtomicBool;
|
||||||
|
|
||||||
use super::{DecoratedHandler, WindowId, WaylandContext};
|
use super::{DecoratedHandler, WindowId, WaylandContext};
|
||||||
|
|
||||||
use wayland_client::EventQueue;
|
|
||||||
|
use wayland_client::{EventQueue, EventQueueHandle, Init, Proxy};
|
||||||
|
use wayland_client::protocol::{wl_seat, wl_surface, wl_pointer, wl_keyboard};
|
||||||
|
|
||||||
|
use super::make_wid;
|
||||||
use super::wayland_window::DecoratedSurface;
|
use super::wayland_window::DecoratedSurface;
|
||||||
|
use super::wayland_kbd::MappedKeyboard;
|
||||||
|
use super::keyboard::KbdHandler;
|
||||||
|
|
||||||
pub struct EventsLoopSink {
|
pub struct EventsLoopSink {
|
||||||
callback: Option<*mut FnMut(::Event)>,
|
callback: Box<FnMut(::Event)>
|
||||||
queue: VecDeque<::Event>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for EventsLoopSink { }
|
unsafe impl Send for EventsLoopSink { }
|
||||||
|
@ -17,21 +25,16 @@ unsafe impl Send for EventsLoopSink { }
|
||||||
impl EventsLoopSink {
|
impl EventsLoopSink {
|
||||||
pub fn new() -> EventsLoopSink {
|
pub fn new() -> EventsLoopSink {
|
||||||
EventsLoopSink {
|
EventsLoopSink {
|
||||||
callback: None,
|
callback: Box::new(|_| {}),
|
||||||
queue: VecDeque::new()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push_event(&mut self, evt: ::WindowEvent, wid: WindowId) {
|
pub fn send_event(&mut self, evt: ::WindowEvent, wid: WindowId) {
|
||||||
let evt = ::Event::WindowEvent {
|
let evt = ::Event::WindowEvent {
|
||||||
event: evt,
|
event: evt,
|
||||||
window_id: ::WindowId(::platform::WindowId::Wayland(wid))
|
window_id: ::WindowId(::platform::WindowId::Wayland(wid))
|
||||||
};
|
};
|
||||||
if let Some(cb) = self.callback {
|
(self.callback)(evt)
|
||||||
unsafe { (&mut *cb)(evt) }
|
|
||||||
} else {
|
|
||||||
self.queue.push_back(evt)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function is only safe of the set callback is unset before exclusive
|
// This function is only safe of the set callback is unset before exclusive
|
||||||
|
@ -39,25 +42,12 @@ impl EventsLoopSink {
|
||||||
//
|
//
|
||||||
// The callback also cannot be used any longer as long as it has not been
|
// The callback also cannot be used any longer as long as it has not been
|
||||||
// cleared from the Sink.
|
// cleared from the Sink.
|
||||||
unsafe fn set_callback(&mut self, cb: &mut FnMut(::Event)) {
|
unsafe fn set_callback(&mut self, cb: Box<FnMut(::Event)>) -> Box<FnMut(::Event)> {
|
||||||
let cb: &mut FnMut(::Event) = ::std::mem::transmute(cb);
|
::std::mem::replace(&mut self.callback, cb)
|
||||||
self.callback = Some(cb as *mut _);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_callback<F: FnOnce(&mut FnMut(::Event))>(&mut self, f: F) {
|
fn with_callback<F: FnOnce(&mut FnMut(::Event))>(&mut self, f: F) {
|
||||||
if let Some(cb) = self.callback {
|
f(&mut *self.callback)
|
||||||
f(unsafe {&mut *cb})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn clear_callback(&mut self) {
|
|
||||||
self.callback = None
|
|
||||||
}
|
|
||||||
|
|
||||||
fn drain_queue<F: FnMut(::Event)>(&mut self, cb: &mut F) {
|
|
||||||
for evt in self.queue.drain(..) {
|
|
||||||
cb(evt)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,30 +57,33 @@ pub struct EventsLoop {
|
||||||
decorated_ids: Mutex<Vec<(usize, WindowId)>>,
|
decorated_ids: Mutex<Vec<(usize, WindowId)>>,
|
||||||
sink: Arc<Mutex<EventsLoopSink>>,
|
sink: Arc<Mutex<EventsLoopSink>>,
|
||||||
interrupted: AtomicBool,
|
interrupted: AtomicBool,
|
||||||
|
hid: usize
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EventsLoop {
|
impl EventsLoop {
|
||||||
pub fn new(ctxt: Arc<WaylandContext>) -> EventsLoop {
|
pub fn new(ctxt: Arc<WaylandContext>) -> EventsLoop {
|
||||||
let evq = ctxt.display.create_event_queue();
|
let mut evq = ctxt.display.create_event_queue();
|
||||||
|
let sink = Arc::new(Mutex::new(EventsLoopSink::new()));
|
||||||
|
let hid = evq.add_handler_with_init(InputHandler::new(&ctxt, sink.clone()));
|
||||||
EventsLoop {
|
EventsLoop {
|
||||||
ctxt: ctxt,
|
ctxt: ctxt,
|
||||||
evq: Arc::new(Mutex::new(evq)),
|
evq: Arc::new(Mutex::new(evq)),
|
||||||
decorated_ids: Mutex::new(Vec::new()),
|
decorated_ids: Mutex::new(Vec::new()),
|
||||||
sink: Arc::new(Mutex::new(EventsLoopSink::new())),
|
sink: sink,
|
||||||
interrupted: AtomicBool::new(false)
|
interrupted: AtomicBool::new(false),
|
||||||
|
hid: hid
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_sink(&self) -> Arc<Mutex<EventsLoopSink>> {
|
|
||||||
self.sink.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_event_queue(&self) -> Arc<Mutex<EventQueue>> {
|
pub fn get_event_queue(&self) -> Arc<Mutex<EventQueue>> {
|
||||||
self.evq.clone()
|
self.evq.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register_window(&self, decorated_id: usize, wid: WindowId) {
|
pub fn register_window(&self, decorated_id: usize, surface: Arc<wl_surface::WlSurface>) {
|
||||||
self.decorated_ids.lock().unwrap().push((decorated_id, wid));
|
self.decorated_ids.lock().unwrap().push((decorated_id, make_wid(&surface)));
|
||||||
|
let mut guard = self.evq.lock().unwrap();
|
||||||
|
let mut state = guard.state();
|
||||||
|
state.get_mut_handler::<InputHandler>(self.hid).windows.push(surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_resize(evq: &mut EventQueue, ids: &[(usize, WindowId)], callback: &mut FnMut(::Event))
|
fn process_resize(evq: &mut EventQueue, ids: &[(usize, WindowId)], callback: &mut FnMut(::Event))
|
||||||
|
@ -123,33 +116,32 @@ impl EventsLoop {
|
||||||
// first of all, get exclusive access to this event queue
|
// first of all, get exclusive access to this event queue
|
||||||
let mut evq_guard = self.evq.lock().unwrap();
|
let mut evq_guard = self.evq.lock().unwrap();
|
||||||
|
|
||||||
// dispatch stored events:
|
|
||||||
self.sink.lock().unwrap().drain_queue(&mut callback);
|
|
||||||
|
|
||||||
// read some events from the socket if some are waiting & queue is empty
|
// read some events from the socket if some are waiting & queue is empty
|
||||||
if let Some(guard) = evq_guard.prepare_read() {
|
if let Some(guard) = evq_guard.prepare_read() {
|
||||||
guard.read_events().expect("Wayland connection unexpectedly lost");
|
guard.read_events().expect("Wayland connection unexpectedly lost");
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the callback into the sink
|
// set the callback into the sink
|
||||||
unsafe { self.sink.lock().unwrap().set_callback(&mut callback) };
|
// we extend the lifetime of the closure to 'static to be able to put it in
|
||||||
|
// the sink, but we'll explicitly drop it at the end of this function, so it's fine
|
||||||
|
let static_cb = unsafe { ::std::mem::transmute(Box::new(callback) as Box<FnMut(_)>) };
|
||||||
|
let old_cb = unsafe { self.sink.lock().unwrap().set_callback(static_cb) };
|
||||||
|
|
||||||
// then do the actual dispatching
|
// then do the actual dispatching
|
||||||
self.ctxt.dispatch_pending();
|
self.ctxt.dispatch_pending();
|
||||||
evq_guard.dispatch_pending().expect("Wayland connection unexpectedly lost");
|
evq_guard.dispatch_pending().expect("Wayland connection unexpectedly lost");
|
||||||
|
|
||||||
let mut sink_guard = self.sink.lock().unwrap();
|
let mut sink_guard = self.sink.lock().unwrap();
|
||||||
|
|
||||||
// events where probably dispatched, process resize
|
// events where probably dispatched, process resize
|
||||||
let ids_guard = self.decorated_ids.lock().unwrap();
|
let ids_guard = self.decorated_ids.lock().unwrap();
|
||||||
sink_guard.with_callback(
|
sink_guard.with_callback(
|
||||||
|cb| Self::process_resize(&mut evq_guard, &ids_guard, cb)
|
|cb| Self::process_resize(&mut evq_guard, &ids_guard, cb)
|
||||||
);
|
);
|
||||||
|
|
||||||
sink_guard.clear_callback();
|
// replace the old noop callback
|
||||||
// we must keep callback alive up to this point!
|
unsafe { self.sink.lock().unwrap().set_callback(old_cb) };
|
||||||
drop(callback);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_forever<F>(&self, mut callback: F)
|
pub fn run_forever<F>(&self, mut callback: F)
|
||||||
|
@ -161,11 +153,11 @@ impl EventsLoop {
|
||||||
// first of all, get exclusive access to this event queue
|
// first of all, get exclusive access to this event queue
|
||||||
let mut evq_guard = self.evq.lock().unwrap();
|
let mut evq_guard = self.evq.lock().unwrap();
|
||||||
|
|
||||||
// dispatch stored events:
|
|
||||||
self.sink.lock().unwrap().drain_queue(&mut callback);
|
|
||||||
|
|
||||||
// set the callback into the sink
|
// set the callback into the sink
|
||||||
unsafe { self.sink.lock().unwrap().set_callback(&mut callback) };
|
// we extend the lifetime of the closure to 'static to be able to put it in
|
||||||
|
// the sink, but we'll explicitly drop it at the end of this function, so it's fine
|
||||||
|
let static_cb = unsafe { ::std::mem::transmute(Box::new(callback) as Box<FnMut(_)>) };
|
||||||
|
let old_cb = unsafe { self.sink.lock().unwrap().set_callback(static_cb) };
|
||||||
|
|
||||||
while !self.interrupted.load(::std::sync::atomic::Ordering::Relaxed) {
|
while !self.interrupted.load(::std::sync::atomic::Ordering::Relaxed) {
|
||||||
self.ctxt.dispatch();
|
self.ctxt.dispatch();
|
||||||
|
@ -177,8 +169,388 @@ impl EventsLoop {
|
||||||
self.ctxt.flush();
|
self.ctxt.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.sink.lock().unwrap().clear_callback();
|
// replace the old noop callback
|
||||||
// we must keep callback alive up to this point!
|
unsafe { self.sink.lock().unwrap().set_callback(old_cb) };
|
||||||
drop(callback)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum KbdType {
|
||||||
|
Mapped(MappedKeyboard<KbdHandler>),
|
||||||
|
Plain(Option<WindowId>)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct InputHandler {
|
||||||
|
my_id: usize,
|
||||||
|
windows: Vec<Arc<wl_surface::WlSurface>>,
|
||||||
|
seat: Option<wl_seat::WlSeat>,
|
||||||
|
mouse: Option<wl_pointer::WlPointer>,
|
||||||
|
mouse_focus: Option<Arc<wl_surface::WlSurface>>,
|
||||||
|
mouse_location: (i32, i32),
|
||||||
|
axis_buffer: Option<(f32, f32)>,
|
||||||
|
axis_discrete_buffer: Option<(i32, i32)>,
|
||||||
|
axis_state: TouchPhase,
|
||||||
|
kbd: Option<wl_keyboard::WlKeyboard>,
|
||||||
|
kbd_handler: KbdType,
|
||||||
|
callback: Arc<Mutex<EventsLoopSink>>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InputHandler {
|
||||||
|
fn new(ctxt: &WaylandContext, sink: Arc<Mutex<EventsLoopSink>>) -> InputHandler {
|
||||||
|
let kbd_handler = match MappedKeyboard::new(KbdHandler::new(sink.clone())) {
|
||||||
|
Ok(h) => KbdType::Mapped(h),
|
||||||
|
Err(_) => KbdType::Plain(None)
|
||||||
|
};
|
||||||
|
InputHandler {
|
||||||
|
my_id: 0,
|
||||||
|
windows: Vec::new(),
|
||||||
|
seat: ctxt.get_seat(),
|
||||||
|
mouse: None,
|
||||||
|
mouse_focus: None,
|
||||||
|
mouse_location: (0,0),
|
||||||
|
axis_buffer: None,
|
||||||
|
axis_discrete_buffer: None,
|
||||||
|
axis_state: TouchPhase::Started,
|
||||||
|
kbd: None,
|
||||||
|
kbd_handler: kbd_handler,
|
||||||
|
callback: sink
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Init for InputHandler {
|
||||||
|
fn init(&mut self, evqh: &mut EventQueueHandle, index: usize) {
|
||||||
|
if let Some(ref seat) = self.seat {
|
||||||
|
evqh.register::<_, InputHandler>(seat, index);
|
||||||
|
}
|
||||||
|
self.my_id = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl wl_seat::Handler for InputHandler {
|
||||||
|
fn capabilities(&mut self,
|
||||||
|
evqh: &mut EventQueueHandle,
|
||||||
|
seat: &wl_seat::WlSeat,
|
||||||
|
capabilities: wl_seat::Capability)
|
||||||
|
{
|
||||||
|
// create pointer if applicable
|
||||||
|
if capabilities.contains(wl_seat::Pointer) && self.mouse.is_none() {
|
||||||
|
let pointer = seat.get_pointer().expect("Seat is not dead");
|
||||||
|
evqh.register::<_, InputHandler>(&pointer, self.my_id);
|
||||||
|
self.mouse = Some(pointer);
|
||||||
|
}
|
||||||
|
// destroy pointer if applicable
|
||||||
|
if !capabilities.contains(wl_seat::Pointer) {
|
||||||
|
if let Some(pointer) = self.mouse.take() {
|
||||||
|
pointer.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// create keyboard if applicable
|
||||||
|
if capabilities.contains(wl_seat::Keyboard) && self.kbd.is_none() {
|
||||||
|
let kbd = seat.get_keyboard().expect("Seat is not dead");
|
||||||
|
evqh.register::<_, InputHandler>(&kbd, self.my_id);
|
||||||
|
self.kbd = Some(kbd);
|
||||||
|
}
|
||||||
|
// destroy keyboard if applicable
|
||||||
|
if !capabilities.contains(wl_seat::Keyboard) {
|
||||||
|
if let Some(kbd) = self.kbd.take() {
|
||||||
|
kbd.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare_handler!(InputHandler, wl_seat::Handler, wl_seat::WlSeat);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pointer Handling
|
||||||
|
*/
|
||||||
|
|
||||||
|
impl wl_pointer::Handler for InputHandler {
|
||||||
|
fn enter(&mut self,
|
||||||
|
_evqh: &mut EventQueueHandle,
|
||||||
|
_proxy: &wl_pointer::WlPointer,
|
||||||
|
_serial: u32,
|
||||||
|
surface: &wl_surface::WlSurface,
|
||||||
|
surface_x: f64,
|
||||||
|
surface_y: f64)
|
||||||
|
{
|
||||||
|
self.mouse_location = (surface_x as i32, surface_y as i32);
|
||||||
|
for window in &self.windows {
|
||||||
|
if window.equals(surface) {
|
||||||
|
self.mouse_focus = Some(window.clone());
|
||||||
|
let (w, h) = self.mouse_location;
|
||||||
|
let mut guard = self.callback.lock().unwrap();
|
||||||
|
guard.send_event(Event::MouseEntered, make_wid(window));
|
||||||
|
guard.send_event(Event::MouseMoved(w, h), make_wid(window));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn leave(&mut self,
|
||||||
|
_evqh: &mut EventQueueHandle,
|
||||||
|
_proxy: &wl_pointer::WlPointer,
|
||||||
|
_serial: u32,
|
||||||
|
surface: &wl_surface::WlSurface)
|
||||||
|
{
|
||||||
|
self.mouse_focus = None;
|
||||||
|
for window in &self.windows {
|
||||||
|
if window.equals(surface) {
|
||||||
|
self.callback.lock().unwrap().send_event(Event::MouseLeft, make_wid(window));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn motion(&mut self,
|
||||||
|
_evqh: &mut EventQueueHandle,
|
||||||
|
_proxy: &wl_pointer::WlPointer,
|
||||||
|
_time: u32,
|
||||||
|
surface_x: f64,
|
||||||
|
surface_y: f64)
|
||||||
|
{
|
||||||
|
self.mouse_location = (surface_x as i32, surface_y as i32);
|
||||||
|
if let Some(ref window) = self.mouse_focus {
|
||||||
|
let (w,h) = self.mouse_location;
|
||||||
|
self.callback.lock().unwrap().send_event(Event::MouseMoved(w, h), make_wid(window));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn button(&mut self,
|
||||||
|
_evqh: &mut EventQueueHandle,
|
||||||
|
_proxy: &wl_pointer::WlPointer,
|
||||||
|
_serial: u32,
|
||||||
|
_time: u32,
|
||||||
|
button: u32,
|
||||||
|
state: wl_pointer::ButtonState)
|
||||||
|
{
|
||||||
|
if let Some(ref window) = self.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
|
||||||
|
};
|
||||||
|
self.callback.lock().unwrap().send_event(Event::MouseInput(state, button), make_wid(window));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn axis(&mut self,
|
||||||
|
_evqh: &mut EventQueueHandle,
|
||||||
|
_proxy: &wl_pointer::WlPointer,
|
||||||
|
_time: u32,
|
||||||
|
axis: wl_pointer::Axis,
|
||||||
|
value: f64)
|
||||||
|
{
|
||||||
|
let (mut x, mut y) = self.axis_buffer.unwrap_or((0.0, 0.0));
|
||||||
|
match axis {
|
||||||
|
wl_pointer::Axis::VerticalScroll => y += value as f32,
|
||||||
|
wl_pointer::Axis::HorizontalScroll => x += value as f32
|
||||||
|
}
|
||||||
|
self.axis_buffer = Some((x,y));
|
||||||
|
self.axis_state = match self.axis_state {
|
||||||
|
TouchPhase::Started | TouchPhase::Moved => TouchPhase::Moved,
|
||||||
|
_ => TouchPhase::Started
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn frame(&mut self,
|
||||||
|
_evqh: &mut EventQueueHandle,
|
||||||
|
_proxy: &wl_pointer::WlPointer)
|
||||||
|
{
|
||||||
|
let axis_buffer = self.axis_buffer.take();
|
||||||
|
let axis_discrete_buffer = self.axis_discrete_buffer.take();
|
||||||
|
if let Some(ref window) = self.mouse_focus {
|
||||||
|
if let Some((x, y)) = axis_discrete_buffer {
|
||||||
|
self.callback.lock().unwrap().send_event(
|
||||||
|
Event::MouseWheel(
|
||||||
|
MouseScrollDelta::LineDelta(x as f32, y as f32),
|
||||||
|
self.axis_state
|
||||||
|
),
|
||||||
|
make_wid(window)
|
||||||
|
);
|
||||||
|
} else if let Some((x, y)) = axis_buffer {
|
||||||
|
self.callback.lock().unwrap().send_event(
|
||||||
|
Event::MouseWheel(
|
||||||
|
MouseScrollDelta::PixelDelta(x as f32, y as f32),
|
||||||
|
self.axis_state
|
||||||
|
),
|
||||||
|
make_wid(window)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn axis_source(&mut self,
|
||||||
|
_evqh: &mut EventQueueHandle,
|
||||||
|
_proxy: &wl_pointer::WlPointer,
|
||||||
|
_axis_source: wl_pointer::AxisSource)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
fn axis_stop(&mut self,
|
||||||
|
_evqh: &mut EventQueueHandle,
|
||||||
|
_proxy: &wl_pointer::WlPointer,
|
||||||
|
_time: u32,
|
||||||
|
_axis: wl_pointer::Axis)
|
||||||
|
{
|
||||||
|
self.axis_state = TouchPhase::Ended;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn axis_discrete(&mut self,
|
||||||
|
_evqh: &mut EventQueueHandle,
|
||||||
|
_proxy: &wl_pointer::WlPointer,
|
||||||
|
axis: wl_pointer::Axis,
|
||||||
|
discrete: i32)
|
||||||
|
{
|
||||||
|
let (mut x, mut y) = self.axis_discrete_buffer.unwrap_or((0,0));
|
||||||
|
match axis {
|
||||||
|
wl_pointer::Axis::VerticalScroll => y += discrete,
|
||||||
|
wl_pointer::Axis::HorizontalScroll => x += discrete
|
||||||
|
}
|
||||||
|
self.axis_discrete_buffer = Some((x,y));
|
||||||
|
self.axis_state = match self.axis_state {
|
||||||
|
TouchPhase::Started | TouchPhase::Moved => TouchPhase::Moved,
|
||||||
|
_ => TouchPhase::Started
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare_handler!(InputHandler, wl_pointer::Handler, wl_pointer::WlPointer);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Keyboard Handling
|
||||||
|
*/
|
||||||
|
|
||||||
|
impl wl_keyboard::Handler for InputHandler {
|
||||||
|
// mostly pass-through
|
||||||
|
fn keymap(&mut self,
|
||||||
|
evqh: &mut EventQueueHandle,
|
||||||
|
proxy: &wl_keyboard::WlKeyboard,
|
||||||
|
format: wl_keyboard::KeymapFormat,
|
||||||
|
fd: ::std::os::unix::io::RawFd,
|
||||||
|
size: u32)
|
||||||
|
{
|
||||||
|
match self.kbd_handler {
|
||||||
|
KbdType::Mapped(ref mut h) => h.keymap(evqh, proxy, format, fd, size),
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn enter(&mut self,
|
||||||
|
evqh: &mut EventQueueHandle,
|
||||||
|
proxy: &wl_keyboard::WlKeyboard,
|
||||||
|
serial: u32,
|
||||||
|
surface: &wl_surface::WlSurface,
|
||||||
|
keys: Vec<u8>)
|
||||||
|
{
|
||||||
|
for window in &self.windows {
|
||||||
|
if window.equals(surface) {
|
||||||
|
self.callback.lock().unwrap().send_event(Event::Focused(true), make_wid(window));
|
||||||
|
match self.kbd_handler {
|
||||||
|
KbdType::Mapped(ref mut h) => {
|
||||||
|
h.handler().target = Some(make_wid(window));
|
||||||
|
h.enter(evqh, proxy, serial, surface, keys);
|
||||||
|
},
|
||||||
|
KbdType::Plain(ref mut target) => {
|
||||||
|
*target = Some(make_wid(window))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn leave(&mut self,
|
||||||
|
evqh: &mut EventQueueHandle,
|
||||||
|
proxy: &wl_keyboard::WlKeyboard,
|
||||||
|
serial: u32,
|
||||||
|
surface: &wl_surface::WlSurface)
|
||||||
|
{
|
||||||
|
for window in &self.windows {
|
||||||
|
if window.equals(surface) {
|
||||||
|
self.callback.lock().unwrap().send_event(Event::Focused(false), make_wid(window));
|
||||||
|
match self.kbd_handler {
|
||||||
|
KbdType::Mapped(ref mut h) => {
|
||||||
|
h.handler().target = None;
|
||||||
|
h.leave(evqh, proxy, serial, surface);
|
||||||
|
},
|
||||||
|
KbdType::Plain(ref mut target) => {
|
||||||
|
*target = None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn key(&mut self,
|
||||||
|
evqh: &mut EventQueueHandle,
|
||||||
|
proxy: &wl_keyboard::WlKeyboard,
|
||||||
|
serial: u32,
|
||||||
|
time: u32,
|
||||||
|
key: u32,
|
||||||
|
state: wl_keyboard::KeyState)
|
||||||
|
{
|
||||||
|
match self.kbd_handler {
|
||||||
|
KbdType::Mapped(ref mut h) => h.key(evqh, proxy, serial, time, key, state),
|
||||||
|
KbdType::Plain(Some(wid)) => {
|
||||||
|
let state = match state {
|
||||||
|
wl_keyboard::KeyState::Pressed => ElementState::Pressed,
|
||||||
|
wl_keyboard::KeyState::Released => ElementState::Released,
|
||||||
|
};
|
||||||
|
// This is fallback impl if libxkbcommon was not available
|
||||||
|
// This case should probably never happen, as most wayland
|
||||||
|
// compositors _need_ libxkbcommon anyway...
|
||||||
|
//
|
||||||
|
// In this case, we don't have the modifiers state information
|
||||||
|
// anyway, as we need libxkbcommon to interpret it (it is
|
||||||
|
// supposed to be serialized by the compositor using libxkbcommon)
|
||||||
|
self.callback.lock().unwrap().send_event(
|
||||||
|
Event::KeyboardInput(
|
||||||
|
state,
|
||||||
|
key as u8,
|
||||||
|
None,
|
||||||
|
ModifiersState::default()
|
||||||
|
),
|
||||||
|
wid
|
||||||
|
);
|
||||||
|
},
|
||||||
|
KbdType::Plain(None) => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn modifiers(&mut self,
|
||||||
|
evqh: &mut EventQueueHandle,
|
||||||
|
proxy: &wl_keyboard::WlKeyboard,
|
||||||
|
serial: u32,
|
||||||
|
mods_depressed: u32,
|
||||||
|
mods_latched: u32,
|
||||||
|
mods_locked: u32,
|
||||||
|
group: u32)
|
||||||
|
{
|
||||||
|
match self.kbd_handler {
|
||||||
|
KbdType::Mapped(ref mut h) => h.modifiers(evqh, proxy, serial, mods_depressed,
|
||||||
|
mods_latched, mods_locked, group),
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn repeat_info(&mut self,
|
||||||
|
evqh: &mut EventQueueHandle,
|
||||||
|
proxy: &wl_keyboard::WlKeyboard,
|
||||||
|
rate: i32,
|
||||||
|
delay: i32)
|
||||||
|
{
|
||||||
|
match self.kbd_handler {
|
||||||
|
KbdType::Mapped(ref mut h) => h.repeat_info(evqh, proxy, rate, delay),
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare_handler!(InputHandler, wl_keyboard::Handler, wl_keyboard::WlKeyboard);
|
||||||
|
|
|
@ -4,17 +4,18 @@ use {VirtualKeyCode, ElementState, WindowEvent as Event};
|
||||||
|
|
||||||
use events::ModifiersState;
|
use events::ModifiersState;
|
||||||
|
|
||||||
use super::{wayland_kbd, make_wid, EventsLoopSink};
|
use super::{wayland_kbd, EventsLoopSink, WindowId};
|
||||||
use wayland_client::EventQueueHandle;
|
use wayland_client::EventQueueHandle;
|
||||||
use wayland_client::protocol::{wl_keyboard, wl_surface};
|
use wayland_client::protocol::wl_keyboard;
|
||||||
|
|
||||||
pub struct KbdHandler {
|
pub struct KbdHandler {
|
||||||
pub target: Option<(Arc<wl_surface::WlSurface>,Arc<Mutex<EventsLoopSink>>)>
|
sink: Arc<Mutex<EventsLoopSink>>,
|
||||||
|
pub target: Option<WindowId>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl KbdHandler {
|
impl KbdHandler {
|
||||||
pub fn new() -> KbdHandler {
|
pub fn new(sink: Arc<Mutex<EventsLoopSink>>) -> KbdHandler {
|
||||||
KbdHandler { target: None }
|
KbdHandler { sink: sink, target: None }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,14 +31,14 @@ impl wayland_kbd::Handler for KbdHandler {
|
||||||
state: wl_keyboard::KeyState,
|
state: wl_keyboard::KeyState,
|
||||||
utf8: Option<String>)
|
utf8: Option<String>)
|
||||||
{
|
{
|
||||||
if let Some((ref window, ref sink)) = self.target {
|
if let Some(wid) = self.target {
|
||||||
let state = match state {
|
let state = match state {
|
||||||
wl_keyboard::KeyState::Pressed => ElementState::Pressed,
|
wl_keyboard::KeyState::Pressed => ElementState::Pressed,
|
||||||
wl_keyboard::KeyState::Released => ElementState::Released,
|
wl_keyboard::KeyState::Released => ElementState::Released,
|
||||||
};
|
};
|
||||||
let vkcode = key_to_vkey(rawkey, keysym);
|
let vkcode = key_to_vkey(rawkey, keysym);
|
||||||
let mut guard = sink.lock().unwrap();
|
let mut guard = self.sink.lock().unwrap();
|
||||||
guard.push_event(
|
guard.send_event(
|
||||||
Event::KeyboardInput(
|
Event::KeyboardInput(
|
||||||
state,
|
state,
|
||||||
rawkey as u8,
|
rawkey as u8,
|
||||||
|
@ -49,13 +50,13 @@ impl wayland_kbd::Handler for KbdHandler {
|
||||||
logo: mods.logo
|
logo: mods.logo
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
make_wid(window)
|
wid
|
||||||
);
|
);
|
||||||
// send char event only on key press, not release
|
// send char event only on key press, not release
|
||||||
if let ElementState::Released = state { return }
|
if let ElementState::Released = state { return }
|
||||||
if let Some(txt) = utf8 {
|
if let Some(txt) = utf8 {
|
||||||
for chr in txt.chars() {
|
for chr in txt.chars() {
|
||||||
guard.push_event(Event::ReceivedCharacter(chr), make_wid(window));
|
guard.send_event(Event::ReceivedCharacter(chr), wid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use wayland_client::{EventQueue, EventQueueHandle, Init, Proxy};
|
use wayland_client::{EventQueue, EventQueueHandle, Proxy};
|
||||||
use wayland_client::protocol::{wl_display,wl_surface,wl_shell_surface};
|
use wayland_client::protocol::{wl_display,wl_surface,wl_shell_surface};
|
||||||
|
|
||||||
use {CreationError, MouseCursor, CursorState, WindowAttributes};
|
use {CreationError, MouseCursor, CursorState, WindowAttributes};
|
||||||
|
@ -31,7 +31,7 @@ impl Window {
|
||||||
{
|
{
|
||||||
let (width, height) = attributes.dimensions.unwrap_or((800,600));
|
let (width, height) = attributes.dimensions.unwrap_or((800,600));
|
||||||
|
|
||||||
let (surface, decorated) = ctxt.create_window::<DecoratedHandler>(evlp.get_sink());
|
let (surface, decorated) = ctxt.create_window::<DecoratedHandler>();
|
||||||
|
|
||||||
// init DecoratedSurface
|
// init DecoratedSurface
|
||||||
let evq = evlp.get_event_queue();
|
let evq = evlp.get_event_queue();
|
||||||
|
@ -67,7 +67,7 @@ impl Window {
|
||||||
decorated_id: decorated_id
|
decorated_id: decorated_id
|
||||||
};
|
};
|
||||||
|
|
||||||
evlp.register_window(me.decorated_id, me.id());
|
evlp.register_window(me.decorated_id, me.surface.clone());
|
||||||
|
|
||||||
Ok(me)
|
Ok(me)
|
||||||
}
|
}
|
||||||
|
@ -165,7 +165,6 @@ impl Window {
|
||||||
impl Drop for Window {
|
impl Drop for Window {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.surface.destroy();
|
self.surface.destroy();
|
||||||
self.ctxt.prune_dead_windows();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue