From 562d6cd1e3c3d0c2e9b0f11b2e21ca06214acd41 Mon Sep 17 00:00:00 2001 From: Victor Berger Date: Sun, 10 May 2015 19:30:57 +0200 Subject: Move WaylandContext in its own file. --- src/api/wayland/context.rs | 124 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 src/api/wayland/context.rs (limited to 'src/api/wayland/context.rs') diff --git a/src/api/wayland/context.rs b/src/api/wayland/context.rs new file mode 100644 index 0000000..44a1f51 --- /dev/null +++ b/src/api/wayland/context.rs @@ -0,0 +1,124 @@ +use super::wayland::core::{Display, Registry, Compositor, Shell, Output, + Seat, Pointer, default_display, WSurface, SurfaceId}; + +use std::collections::{VecDeque, HashMap}; +use std::sync::{Arc, Mutex}; + +use Event; + +pub struct WaylandContext { + pub display: Display, + pub registry: Registry, + pub compositor: Compositor, + pub shell: Shell, + pub seat: Seat, + pub pointer: Option>, + windows_event_queues: Arc>>>>>, + current_pointer_surface: Arc>>, + pub outputs: Vec> +} + +impl WaylandContext { + pub fn new() -> Option { + let display = match default_display() { + Some(d) => d, + None => return None, + }; + let registry = display.get_registry(); + // let the registry get its events + display.sync_roundtrip(); + let compositor = match registry.get_compositor() { + Some(c) => c, + None => return None, + }; + let shell = match registry.get_shell() { + Some(s) => s, + None => return None, + }; + let seat = match registry.get_seats().into_iter().next() { + Some(s) => s, + None => return None, + }; + let outputs = registry.get_outputs().into_iter().map(Arc::new).collect::>(); + // let the other globals get their events + display.sync_roundtrip(); + + let current_pointer_surface = Arc::new(Mutex::new(None)); + + // rustc has trouble finding the correct type here, so we explicit it. + let windows_event_queues = Arc::new(Mutex::new( + HashMap::>>>::new() + )); + + // handle inputs + let mut pointer = seat.get_pointer(); + if let Some(ref mut p) = pointer { + // set the enter/leave callbacks + let current_surface = current_pointer_surface.clone(); + p.set_enter_action(move |_, sid, x, y| { + *current_surface.lock().unwrap() = Some(sid); + }); + let current_surface = current_pointer_surface.clone(); + p.set_leave_action(move |_, sid| { + *current_surface.lock().unwrap() = None; + }); + // set the events callbacks + let current_surface = current_pointer_surface.clone(); + let event_queues = windows_event_queues.clone(); + p.set_motion_action(move |_, _, x, y| { + // dispatch to the appropriate queue + let sid = *current_surface.lock().unwrap(); + if let Some(sid) = sid { + let map = event_queues.lock().unwrap(); + if let Some(queue) = map.get(&sid) { + queue.lock().unwrap().push_back(Event::Moved(x as i32,y as i32)) + } + } + }); + let current_surface = current_pointer_surface.clone(); + let event_queues = windows_event_queues.clone(); + p.set_button_action(move |_, sid, b, s| { + use super::wayland::core::ButtonState; + use MouseButton; + use ElementState; + let button = match b { + 0x110 => MouseButton::Left, + 0x111 => MouseButton::Right, + 0x112 => MouseButton::Middle, + _ => return + }; + let state = match s { + ButtonState::WL_POINTER_BUTTON_STATE_RELEASED => ElementState::Released, + ButtonState::WL_POINTER_BUTTON_STATE_PRESSED => ElementState::Pressed + }; + // dispatch to the appropriate queue + let sid = *current_surface.lock().unwrap(); + if let Some(sid) = sid { + let map = event_queues.lock().unwrap(); + if let Some(queue) = map.get(&sid) { + queue.lock().unwrap().push_back(Event::MouseInput(state, button)) + } + } + }); + } + Some(WaylandContext { + display: display, + registry: registry, + compositor: compositor, + shell: shell, + seat: seat, + pointer: pointer, + windows_event_queues: windows_event_queues, + current_pointer_surface: current_pointer_surface, + outputs: outputs + }) + } + + pub fn register_surface(&self, sid: SurfaceId, queue: Arc>>) { + self.windows_event_queues.lock().unwrap().insert(sid, queue); + } + + pub fn deregister_surface(&self, sid: SurfaceId) { + self.windows_event_queues.lock().unwrap().remove(&sid); + } +} \ No newline at end of file -- cgit v1.2.3