From 1b25d705ce2110b097b98f37f5e7dd9dc3a9d82c Mon Sep 17 00:00:00 2001 From: Victor Berger Date: Tue, 8 Dec 2015 22:54:06 +0100 Subject: api/wayland: move window and monitor to mods. --- src/api/wayland/window.rs | 180 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 src/api/wayland/window.rs (limited to 'src/api/wayland/window.rs') diff --git a/src/api/wayland/window.rs b/src/api/wayland/window.rs new file mode 100644 index 0000000..df50731 --- /dev/null +++ b/src/api/wayland/window.rs @@ -0,0 +1,180 @@ +use {ContextError, CreationError, CursorState, Event, GlAttributes, GlContext, + MouseCursor, PixelFormat, PixelFormatRequirements, WindowAttributes}; + +use api::egl::Context as EglContext; + +use libc; + +#[derive(Clone)] +pub struct WindowProxy; + +impl WindowProxy { + #[inline] + pub fn wakeup_event_loop(&self) { + unimplemented!() + } +} + +pub struct Window { + pub context: EglContext, +} + +pub struct PollEventsIterator<'a> { + window: &'a Window, +} + +impl<'a> Iterator for PollEventsIterator<'a> { + type Item = Event; + + fn next(&mut self) -> Option { + unimplemented!() + } +} + +pub struct WaitEventsIterator<'a> { + window: &'a Window, +} + +impl<'a> Iterator for WaitEventsIterator<'a> { + type Item = Event; + + fn next(&mut self) -> Option { + unimplemented!() + } +} + +impl Window { + pub fn new(window: &WindowAttributes, pf_reqs: &PixelFormatRequirements, + opengl: &GlAttributes<&Window>) -> Result + { + // not implemented + assert!(window.min_dimensions.is_none()); + assert!(window.max_dimensions.is_none()); + + unimplemented!() + } + + pub fn set_title(&self, title: &str) { + unimplemented!() + } + + #[inline] + pub fn show(&self) { + unimplemented!() + } + + #[inline] + pub fn hide(&self) { + unimplemented!() + } + + #[inline] + pub fn get_position(&self) -> Option<(i32, i32)> { + unimplemented!() + } + + #[inline] + pub fn set_position(&self, _x: i32, _y: i32) { + unimplemented!() + } + + pub fn get_inner_size(&self) -> Option<(u32, u32)> { + unimplemented!() + } + + #[inline] + pub fn get_outer_size(&self) -> Option<(u32, u32)> { + unimplemented!() + } + + #[inline] + pub fn set_inner_size(&self, x: u32, y: u32) { + unimplemented!() + } + + #[inline] + pub fn create_window_proxy(&self) -> WindowProxy { + WindowProxy + } + + #[inline] + pub fn poll_events(&self) -> PollEventsIterator { + PollEventsIterator { + window: self + } + } + + #[inline] + pub fn wait_events(&self) -> WaitEventsIterator { + WaitEventsIterator { + window: self + } + } + + #[inline] + pub fn set_window_resize_callback(&mut self, callback: Option) { + unimplemented!() + } + + #[inline] + pub fn set_cursor(&self, cursor: MouseCursor) { + unimplemented!() + } + + #[inline] + pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> { + unimplemented!() + } + + #[inline] + pub fn hidpi_factor(&self) -> f32 { + 1.0 + } + + #[inline] + pub fn set_cursor_position(&self, x: i32, y: i32) -> Result<(), ()> { + unimplemented!() + } + + #[inline] + pub fn platform_display(&self) -> *mut libc::c_void { + unimplemented!() + } + + #[inline] + pub fn platform_window(&self) -> *mut libc::c_void { + unimplemented!() + } +} + +impl GlContext for Window { + #[inline] + unsafe fn make_current(&self) -> Result<(), ContextError> { + self.context.make_current() + } + + #[inline] + fn is_current(&self) -> bool { + self.context.is_current() + } + + #[inline] + fn get_proc_address(&self, addr: &str) -> *const () { + self.context.get_proc_address(addr) + } + + #[inline] + fn swap_buffers(&self) -> Result<(), ContextError> { + self.context.swap_buffers() + } + + #[inline] + fn get_api(&self) -> ::Api { + self.context.get_api() + } + + #[inline] + fn get_pixel_format(&self) -> PixelFormat { + self.context.get_pixel_format().clone() + } +} -- cgit v1.2.3 From 6294d3c7ddc303913c83fd74d14c7a801d496c9e Mon Sep 17 00:00:00 2001 From: Victor Berger Date: Sun, 13 Dec 2015 11:43:39 +0100 Subject: api/wayland: core windows and events structure. --- src/api/wayland/context.rs | 94 ++++++++++++++++++++++++++-- src/api/wayland/events.rs | 10 +++ src/api/wayland/mod.rs | 1 + src/api/wayland/window.rs | 153 +++++++++++++++++++++++++++++++++++++++------ 4 files changed, 234 insertions(+), 24 deletions(-) create mode 100644 src/api/wayland/events.rs (limited to 'src/api/wayland/window.rs') diff --git a/src/api/wayland/context.rs b/src/api/wayland/context.rs index 4fc743b..8e1196d 100644 --- a/src/api/wayland/context.rs +++ b/src/api/wayland/context.rs @@ -1,11 +1,21 @@ -use wayland_client::EventIterator; +use Event as GlutinEvent; + +use std::collections::{HashMap, VecDeque}; +use std::sync::{Arc, Mutex}; + +use libc::c_void; + +use wayland_client::{EventIterator, Proxy, ProxyId}; use wayland_client::wayland::get_display; -use wayland_client::wayland::compositor::WlCompositor; +use wayland_client::wayland::compositor::{WlCompositor, WlSurface}; +use wayland_client::wayland::output::WlOutput; use wayland_client::wayland::seat::WlSeat; use wayland_client::wayland::shell::WlShell; use wayland_client::wayland::shm::WlShm; use wayland_client::wayland::subcompositor::WlSubcompositor; +use super::wayland_window::DecoratedSurface; + lazy_static! { pub static ref WAYLAND_CONTEXT: Option = { WaylandContext::init() @@ -22,7 +32,9 @@ wayland_env!(InnerEnv, pub struct WaylandContext { inner: InnerEnv, - iterator: EventIterator + iterator: Mutex, + monitors: Vec, + queues: Mutex>>>> } impl WaylandContext { @@ -32,11 +44,81 @@ impl WaylandContext { None => return None }; - let (inner_env, iterator) = InnerEnv::init(display); + let (mut inner_env, iterator) = InnerEnv::init(display); + + let monitors = inner_env.globals.iter() + .flat_map(|&(id, _, _)| inner_env.rebind_id::(id)) + .map(|(monitor, _)| monitor) + .collect(); + + inner_env.display.sync_roundtrip().unwrap(); Some(WaylandContext { inner: inner_env, - iterator: iterator + iterator: Mutex::new(iterator), + monitors: monitors, + queues: Mutex::new(HashMap::new()) }) } -} \ No newline at end of file + + pub fn new_surface(&self) -> Option<(WlSurface, Arc>>)> { + self.inner.compositor.as_ref().map(|c| { + let s = c.0.create_surface(); + let id = s.id(); + let queue = { + let mut q = VecDeque::new(); + q.push_back(GlutinEvent::Refresh); + Arc::new(Mutex::new(q)) + }; + self.queues.lock().unwrap().insert(id, queue.clone()); + (s, queue) + }) + } + + pub fn dropped_surface(&self, id: ProxyId) { + self.queues.lock().unwrap().remove(&id); + } + + pub fn decorated_from(&self, surface: &WlSurface, width: i32, height: i32) -> Option { + let inner = &self.inner; + match (&inner.compositor, &inner.subcompositor, &inner.shm, &inner.shell) { + (&Some(ref compositor), &Some(ref subcompositor), &Some(ref shm), &Some(ref shell)) => { + DecoratedSurface::new( + surface, width, height, + &compositor.0, &subcompositor.0, &shm.0, &shell.0, + self.inner.rebind::().map(|(seat, _)| seat) + ).ok() + } + _ => None + } + } + + pub fn display_ptr(&self) -> *const c_void { + self.inner.display.ptr() as *const _ + } + + pub fn dispatch_events(&self) { + self.inner.display.dispatch_pending().unwrap(); + let mut iterator = self.iterator.lock().unwrap(); + let queues = self.queues.lock().unwrap(); + for evt in &mut *iterator { + if let Some((evt, id)) = super::events::translate_event(evt) { + if let Some(q) = queues.get(&id) { + q.lock().unwrap().push_back(evt); + } + } + } + } + + pub fn flush_events(&self) -> ::std::io::Result { + self.inner.display.flush() + } + + pub fn read_events(&self) -> ::std::io::Result> { + let guard = match self.inner.display.prepare_read() { + Some(g) => g, + None => return Ok(None) + }; + return guard.read_events().map(|i| Some(i)); + } +} diff --git a/src/api/wayland/events.rs b/src/api/wayland/events.rs new file mode 100644 index 0000000..86f0575 --- /dev/null +++ b/src/api/wayland/events.rs @@ -0,0 +1,10 @@ +use Event as GlutinEvent; + +use wayland_client::Event as WaylandEvent; +use wayland_client::ProxyId; + +pub fn translate_event(evt: WaylandEvent) -> Option<(GlutinEvent, ProxyId)> { + match evt { + _ => None + } +} \ No newline at end of file diff --git a/src/api/wayland/mod.rs b/src/api/wayland/mod.rs index f30389c..f2e3b2f 100644 --- a/src/api/wayland/mod.rs +++ b/src/api/wayland/mod.rs @@ -7,6 +7,7 @@ extern crate wayland_kbd; extern crate wayland_window; mod context; +mod events; mod monitor; mod window; diff --git a/src/api/wayland/window.rs b/src/api/wayland/window.rs index df50731..7532443 100644 --- a/src/api/wayland/window.rs +++ b/src/api/wayland/window.rs @@ -1,9 +1,18 @@ +use std::collections::VecDeque; +use std::ffi::CString; +use std::sync::{Arc, Mutex}; + +use libc; + use {ContextError, CreationError, CursorState, Event, GlAttributes, GlContext, MouseCursor, PixelFormat, PixelFormatRequirements, WindowAttributes}; - +use api::dlopen; +use api::egl; use api::egl::Context as EglContext; -use libc; +use wayland_client::egl as wegl; +use super::wayland_window::{DecoratedSurface, add_borders, substract_borders}; +use super::context::{WaylandContext, WAYLAND_CONTEXT}; #[derive(Clone)] pub struct WindowProxy; @@ -16,9 +25,36 @@ impl WindowProxy { } pub struct Window { + wayland_context: &'static WaylandContext, + egl_surface: wegl::WlEglSurface, + decorated_surface: Mutex, + evt_queue: Arc>>, + inner_size: Mutex<(i32, i32)>, + resize_callback: Option, pub context: EglContext, } +impl Window { + fn next_event(&self) -> Option { + let mut newsize = None; + for (_, w, h) in &mut *self.decorated_surface.lock().unwrap() { + newsize = Some((w, h)); + } + if let Some((w, h)) = newsize { + let (w, h) = substract_borders(w, h); + *self.inner_size.lock().unwrap() = (w, h); + self.decorated_surface.lock().unwrap().resize(w, h); + self.egl_surface.resize(w, h, 0, 0); + if let Some(f) = self.resize_callback { + f(w as u32, h as u32); + } + Some(Event::Resized(w as u32, h as u32)) + } else { + self.evt_queue.lock().unwrap().pop_front() + } + } +} + pub struct PollEventsIterator<'a> { window: &'a Window, } @@ -27,7 +63,13 @@ impl<'a> Iterator for PollEventsIterator<'a> { type Item = Event; fn next(&mut self) -> Option { - unimplemented!() + match self.window.next_event() { + Some(evt) => return Some(evt), + None => {} + } + // the queue was empty, try a dispatch and see the result + self.window.wayland_context.dispatch_events(); + return self.window.next_event(); } } @@ -39,7 +81,21 @@ impl<'a> Iterator for WaitEventsIterator<'a> { type Item = Event; fn next(&mut self) -> Option { - unimplemented!() + loop { + match self.window.next_event() { + Some(evt) => return Some(evt), + None => {} + } + // the queue was empty, try a dispatch & read and see the result + self.window.wayland_context.flush_events().expect("Connexion with the wayland compositor lost."); + match self.window.wayland_context.read_events() { + Ok(_) => { + // events were read or dispatch is needed, in both cases, we dispatch + self.window.wayland_context.dispatch_events() + } + Err(_) => panic!("Connexion with the wayland compositor lost.") + } + } } } @@ -51,45 +107,97 @@ impl Window { assert!(window.min_dimensions.is_none()); assert!(window.max_dimensions.is_none()); - unimplemented!() + let wayland_context = match *WAYLAND_CONTEXT { + Some(ref c) => c, + None => return Err(CreationError::NotSupported), + }; + + if !wegl::is_available() { + return Err(CreationError::NotSupported) + } + + let (w, h) = window.dimensions.unwrap_or((800, 600)); + + let (surface, evt_queue) = match wayland_context.new_surface() { + Some(t) => t, + None => return Err(CreationError::NotSupported) + }; + + let egl_surface = wegl::WlEglSurface::new(surface, w as i32, h as i32); + + let context = { + let libegl = unsafe { dlopen::dlopen(b"libEGL.so\0".as_ptr() as *const _, dlopen::RTLD_NOW) }; + if libegl.is_null() { + return Err(CreationError::NotSupported); + } + let egl = ::api::egl::ffi::egl::Egl::load_with(|sym| { + let sym = CString::new(sym).unwrap(); + unsafe { dlopen::dlsym(libegl, sym.as_ptr()) } + }); + try!(EglContext::new( + egl, + pf_reqs, &opengl.clone().map_sharing(|_| unimplemented!()), // TODO: + egl::NativeDisplay::Wayland(Some(wayland_context.display_ptr() as *const _))) + .and_then(|p| p.finish(unsafe { egl_surface.egl_surfaceptr() } as *const _)) + ) + }; + + let decorated_surface = match wayland_context.decorated_from(&egl_surface, w as i32, h as i32) { + Some(s) => s, + None => return Err(CreationError::NotSupported) + }; + + Ok(Window { + wayland_context: wayland_context, + egl_surface: egl_surface, + decorated_surface: Mutex::new(decorated_surface), + evt_queue: evt_queue, + inner_size: Mutex::new((w as i32, h as i32)), + resize_callback: None, + context: context + }) } pub fn set_title(&self, title: &str) { - unimplemented!() + self.decorated_surface.lock().unwrap().set_title(title.into()) } #[inline] pub fn show(&self) { - unimplemented!() + // TODO } #[inline] pub fn hide(&self) { - unimplemented!() + // TODO } #[inline] pub fn get_position(&self) -> Option<(i32, i32)> { - unimplemented!() + // Not possible with wayland + None } #[inline] pub fn set_position(&self, _x: i32, _y: i32) { - unimplemented!() + // Not possible with wayland } pub fn get_inner_size(&self) -> Option<(u32, u32)> { - unimplemented!() + let (w, h) = *self.inner_size.lock().unwrap(); + Some((w as u32, h as u32)) } #[inline] pub fn get_outer_size(&self) -> Option<(u32, u32)> { - unimplemented!() + let (w, h) = *self.inner_size.lock().unwrap(); + let (w, h) = add_borders(w, h); + Some((w as u32, h as u32)) } #[inline] pub fn set_inner_size(&self, x: u32, y: u32) { - unimplemented!() + self.decorated_surface.lock().unwrap().resize(x as i32, y as i32) } #[inline] @@ -113,17 +221,18 @@ impl Window { #[inline] pub fn set_window_resize_callback(&mut self, callback: Option) { - unimplemented!() + self.resize_callback = callback; } #[inline] pub fn set_cursor(&self, cursor: MouseCursor) { - unimplemented!() + // TODO } #[inline] pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> { - unimplemented!() + // TODO + Ok(()) } #[inline] @@ -132,8 +241,9 @@ impl Window { } #[inline] - pub fn set_cursor_position(&self, x: i32, y: i32) -> Result<(), ()> { - unimplemented!() + pub fn set_cursor_position(&self, _x: i32, _y: i32) -> Result<(), ()> { + // TODO: not yet possible on wayland + Ok(()) } #[inline] @@ -178,3 +288,10 @@ impl GlContext for Window { self.context.get_pixel_format().clone() } } + +impl Drop for Window { + fn drop(&mut self) { + use wayland_client::Proxy; + self.wayland_context.dropped_surface((*self.egl_surface).id()) + } +} \ No newline at end of file -- cgit v1.2.3 From 0792557f4bc05125f0181729a6adbaf1aa52ec27 Mon Sep 17 00:00:00 2001 From: Victor Berger Date: Sun, 13 Dec 2015 13:13:20 +0100 Subject: api/wayland: pointer events support. --- src/api/wayland/context.rs | 33 ++++++++++++++--- src/api/wayland/events.rs | 91 +++++++++++++++++++++++++++++++++++++++++++++- src/api/wayland/window.rs | 4 +- 3 files changed, 119 insertions(+), 9 deletions(-) (limited to 'src/api/wayland/window.rs') diff --git a/src/api/wayland/context.rs b/src/api/wayland/context.rs index 8e1196d..4b39d85 100644 --- a/src/api/wayland/context.rs +++ b/src/api/wayland/context.rs @@ -1,6 +1,6 @@ use Event as GlutinEvent; -use std::collections::{HashMap, VecDeque}; +use std::collections::{HashMap, VecDeque, HashSet}; use std::sync::{Arc, Mutex}; use libc::c_void; @@ -9,7 +9,7 @@ use wayland_client::{EventIterator, Proxy, ProxyId}; use wayland_client::wayland::get_display; use wayland_client::wayland::compositor::{WlCompositor, WlSurface}; use wayland_client::wayland::output::WlOutput; -use wayland_client::wayland::seat::WlSeat; +use wayland_client::wayland::seat::{WlSeat, WlPointer}; use wayland_client::wayland::shell::WlShell; use wayland_client::wayland::shm::WlShm; use wayland_client::wayland::subcompositor::WlSubcompositor; @@ -30,11 +30,20 @@ wayland_env!(InnerEnv, subcompositor: WlSubcompositor ); +pub struct WaylandFocuses { + pub pointer: Option, + pub pointer_on: Option, + pub pointer_at: Option<(f64, f64)>, + pub keyboard_on: Option +} + pub struct WaylandContext { inner: InnerEnv, iterator: Mutex, monitors: Vec, - queues: Mutex>>>> + queues: Mutex>>>>, + known_surfaces: Mutex>, + focuses: Mutex } impl WaylandContext { @@ -57,7 +66,14 @@ impl WaylandContext { inner: inner_env, iterator: Mutex::new(iterator), monitors: monitors, - queues: Mutex::new(HashMap::new()) + queues: Mutex::new(HashMap::new()), + known_surfaces: Mutex::new(HashSet::new()), + focuses: Mutex::new(WaylandFocuses { + pointer: None, + pointer_on: None, + pointer_at: None, + keyboard_on: None + }) }) } @@ -71,12 +87,14 @@ impl WaylandContext { Arc::new(Mutex::new(q)) }; self.queues.lock().unwrap().insert(id, queue.clone()); + self.known_surfaces.lock().unwrap().insert(id); (s, queue) }) } pub fn dropped_surface(&self, id: ProxyId) { self.queues.lock().unwrap().remove(&id); + self.known_surfaces.lock().unwrap().remove(&id); } pub fn decorated_from(&self, surface: &WlSurface, width: i32, height: i32) -> Option { @@ -100,9 +118,14 @@ impl WaylandContext { pub fn dispatch_events(&self) { self.inner.display.dispatch_pending().unwrap(); let mut iterator = self.iterator.lock().unwrap(); + let mut focuses = self.focuses.lock().unwrap(); + let known_ids = self.known_surfaces.lock().unwrap(); let queues = self.queues.lock().unwrap(); for evt in &mut *iterator { - if let Some((evt, id)) = super::events::translate_event(evt) { + if let Some((evt, id)) = super::events::translate_event( + evt, &mut *focuses, &known_ids, + self.inner.seat.as_ref().map(|s| &s.0)) + { if let Some(q) = queues.get(&id) { q.lock().unwrap().push_back(evt); } diff --git a/src/api/wayland/events.rs b/src/api/wayland/events.rs index 86f0575..6a7a2e7 100644 --- a/src/api/wayland/events.rs +++ b/src/api/wayland/events.rs @@ -1,10 +1,97 @@ +use std::collections::HashSet; + use Event as GlutinEvent; +use ElementState; +use MouseButton; +use MouseScrollDelta; use wayland_client::Event as WaylandEvent; use wayland_client::ProxyId; +use wayland_client::wayland::WaylandProtocolEvent as WPE; +use wayland_client::wayland::seat::{WlSeat, WlSeatEvent, WlPointerEvent, + WlPointerButtonState, + WlPointerAxis, WlSeatCapability}; + +use super::context::WaylandFocuses; -pub fn translate_event(evt: WaylandEvent) -> Option<(GlutinEvent, ProxyId)> { - match evt { +pub fn translate_event( + evt: WaylandEvent, + focuses: &mut WaylandFocuses, + known_surfaces: &HashSet, + seat: Option<&WlSeat>, +) -> Option<(GlutinEvent, ProxyId)> { + let WaylandEvent::Wayland(wayland_evt) = evt; + match wayland_evt { + WPE::WlSeat(_, seat_evt) => match seat_evt { + WlSeatEvent::Capabilities(cap) => { + if cap.contains(WlSeatCapability::Pointer) && focuses.pointer.is_none() { + if let Some(seat) = seat { + focuses.pointer = Some(seat.get_pointer()); + } + } + None + }, + _ => None + }, + WPE::WlPointer(_, pointer_evt) => match pointer_evt { + WlPointerEvent::Enter(_, surface, x, y) => { + if known_surfaces.contains(&surface) { + focuses.pointer_on = Some(surface); + focuses.pointer_at = Some((x, y)); + Some((GlutinEvent::MouseMoved((x as i32, y as i32)), surface)) + } else { + None + } + } + WlPointerEvent::Leave(_, _) => { + focuses.pointer_on = None; + focuses.pointer_at = None; + None + } + WlPointerEvent::Motion(_, x, y) => { + if let Some(surface) = focuses.pointer_on { + focuses.pointer_at = Some((x, y)); + Some((GlutinEvent::MouseMoved((x as i32, y as i32)), surface)) + } else { + None + } + } + WlPointerEvent::Button(_, _, button, state) => { + if let Some(surface) = focuses.pointer_on { + Some((GlutinEvent::MouseInput( + match state { + WlPointerButtonState::Pressed => ElementState::Pressed, + WlPointerButtonState::Released => ElementState::Released + }, + match button { + 0x110 => MouseButton::Left, + 0x111 => MouseButton::Right, + 0x112 => MouseButton::Middle, + // TODO figure out the translation ? + _ => return None + } + ), surface)) + } else { + None + } + } + WlPointerEvent::Axis(_, axis, amplitude) => { + if let Some(surface) = focuses.pointer_on { + Some((GlutinEvent::MouseWheel( + match axis { + WlPointerAxis::VerticalScroll => { + MouseScrollDelta::PixelDelta(amplitude as f32, 0.0) + } + WlPointerAxis::HorizontalScroll => { + MouseScrollDelta::PixelDelta(0.0, amplitude as f32) + } + } + ), surface)) + } else { + None + } + } + }, _ => None } } \ No newline at end of file diff --git a/src/api/wayland/window.rs b/src/api/wayland/window.rs index 7532443..faf772e 100644 --- a/src/api/wayland/window.rs +++ b/src/api/wayland/window.rs @@ -225,12 +225,12 @@ impl Window { } #[inline] - pub fn set_cursor(&self, cursor: MouseCursor) { + pub fn set_cursor(&self, _cursor: MouseCursor) { // TODO } #[inline] - pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> { + pub fn set_cursor_state(&self, _state: CursorState) -> Result<(), String> { // TODO Ok(()) } -- cgit v1.2.3 From 42551d20fdab796548e42e8699ba7d905417d257 Mon Sep 17 00:00:00 2001 From: Victor Berger Date: Tue, 22 Dec 2015 14:35:15 +0100 Subject: api/wayland: output and fullscreen handling. --- src/api/wayland/context.rs | 63 +++++++++++++++++++++++++++++--- src/api/wayland/monitor.rs | 59 ++++++++++++++++++++++++++---- src/api/wayland/window.rs | 90 ++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 190 insertions(+), 22 deletions(-) (limited to 'src/api/wayland/window.rs') diff --git a/src/api/wayland/context.rs b/src/api/wayland/context.rs index 285f50c..f303b54 100644 --- a/src/api/wayland/context.rs +++ b/src/api/wayland/context.rs @@ -10,7 +10,7 @@ use wayland_client::wayland::get_display; use wayland_client::wayland::compositor::{WlCompositor, WlSurface}; use wayland_client::wayland::output::WlOutput; use wayland_client::wayland::seat::{WlSeat, WlPointer}; -use wayland_client::wayland::shell::WlShell; +use wayland_client::wayland::shell::{WlShell, WlShellSurface}; use wayland_client::wayland::shm::WlShm; use wayland_client::wayland::subcompositor::WlSubcompositor; @@ -42,7 +42,7 @@ pub struct WaylandFocuses { pub struct WaylandContext { inner: InnerEnv, iterator: Mutex, - monitors: Vec, + monitors: Vec<(WlOutput, u32, u32, String)>, queues: Mutex>>>>, known_surfaces: Mutex>, focuses: Mutex @@ -57,13 +57,19 @@ impl WaylandContext { let (mut inner_env, iterator) = InnerEnv::init(display); - let monitors = inner_env.globals.iter() + let mut outputs_events = EventIterator::new(); + + let mut monitors = inner_env.globals.iter() .flat_map(|&(id, _, _)| inner_env.rebind_id::(id)) - .map(|(monitor, _)| monitor) - .collect(); + .map(|(mut monitor, _)| { + monitor.set_evt_iterator(&outputs_events); + (monitor, 0, 0, String::new()) + }).collect(); inner_env.display.sync_roundtrip().unwrap(); + super::monitor::init_monitors(&mut monitors, outputs_events); + Some(WaylandContext { inner: inner_env, iterator: Mutex::new(iterator), @@ -114,6 +120,31 @@ impl WaylandContext { } } + pub fn plain_from(&self, surface: &WlSurface, fullscreen: Option) -> Option { + use wayland_client::wayland::shell::WlShellSurfaceFullscreenMethod; + + let inner = &self.inner; + if let Some((ref shell, _)) = inner.shell { + let shell_surface = shell.get_shell_surface(surface); + if let Some(monitor_id) = fullscreen { + for m in &self.monitors { + if m.0.id() == monitor_id { + shell_surface.set_fullscreen( + WlShellSurfaceFullscreenMethod::Default, + 0, + Some(&m.0) + ); + return Some(shell_surface) + } + } + } + shell_surface.set_toplevel(); + Some(shell_surface) + } else { + None + } + } + pub fn display_ptr(&self) -> *const c_void { self.inner.display.ptr() as *const _ } @@ -155,4 +186,26 @@ impl WaylandContext { }; return guard.read_events().map(|i| Some(i)); } + + pub fn monitor_ids(&self) -> Vec { + self.monitors.iter().map(|o| o.0.id()).collect() + } + + pub fn monitor_name(&self, pid: ProxyId) -> Option { + for o in &self.monitors { + if o.0.id() == pid { + return Some(o.3.clone()) + } + } + None + } + + pub fn monitor_dimensions(&self, pid: ProxyId) -> Option<(u32, u32)> { + for o in &self.monitors { + if o.0.id() == pid { + return Some((o.1, o.2)) + } + } + None + } } diff --git a/src/api/wayland/monitor.rs b/src/api/wayland/monitor.rs index 3a42f1f..d87d4b6 100644 --- a/src/api/wayland/monitor.rs +++ b/src/api/wayland/monitor.rs @@ -1,28 +1,75 @@ use std::collections::VecDeque; +use wayland_client::{ProxyId, EventIterator}; +use wayland_client::wayland::output::WlOutput; + +use super::context::WAYLAND_CONTEXT; + #[derive(Clone)] -pub struct MonitorId; +pub struct MonitorId(ProxyId); #[inline] pub fn get_available_monitors() -> VecDeque { - unimplemented!() + WAYLAND_CONTEXT.as_ref().map(|ctxt| + ctxt.monitor_ids().into_iter().map(MonitorId).collect() + ).unwrap_or(VecDeque::new()) } #[inline] pub fn get_primary_monitor() -> MonitorId { - unimplemented!() + WAYLAND_CONTEXT.as_ref().and_then(|ctxt| + ctxt.monitor_ids().into_iter().next().map(MonitorId) + ).expect("wayland: No monitor available.") } impl MonitorId { pub fn get_name(&self) -> Option { - unimplemented!() + WAYLAND_CONTEXT.as_ref().and_then(|ctxt| ctxt.monitor_name(self.0)) } #[inline] pub fn get_native_identifier(&self) -> ::native_monitor::NativeMonitorId { - unimplemented!() + ::native_monitor::NativeMonitorId::Unavailable } pub fn get_dimensions(&self) -> (u32, u32) { - unimplemented!() + WAYLAND_CONTEXT.as_ref().and_then(|ctxt| ctxt.monitor_dimensions(self.0)).unwrap() + } +} + +pub fn proxid_from_monitorid(x: &MonitorId) -> ProxyId { + x.0 +} + +pub fn init_monitors(outputs: &mut Vec<(WlOutput, u32, u32, String)>, evts: EventIterator) { + use wayland_client::{Event, Proxy}; + use wayland_client::wayland::WaylandProtocolEvent; + use wayland_client::wayland::output::{WlOutputEvent, WlOutputMode}; + + for evt in evts { + match evt { + Event::Wayland(WaylandProtocolEvent::WlOutput(pid, oevt)) => match oevt { + WlOutputEvent::Geometry(_, _, _, _, _, maker, model, _) => { + for o in outputs.iter_mut() { + if o.0.id() == pid { + o.3 = format!("{} - {}", maker, model); + break + } + } + }, + WlOutputEvent::Mode(flags, width, height, _) => { + if flags.contains(WlOutputMode::Current) { + for o in outputs.iter_mut() { + if o.0.id() == pid { + o.1 = width as u32; + o.2 = height as u32; + break + } + } + } + }, + _ => {} + }, + _ => {} + } } } \ No newline at end of file diff --git a/src/api/wayland/window.rs b/src/api/wayland/window.rs index faf772e..a9285fa 100644 --- a/src/api/wayland/window.rs +++ b/src/api/wayland/window.rs @@ -9,8 +9,11 @@ use {ContextError, CreationError, CursorState, Event, GlAttributes, GlContext, use api::dlopen; use api::egl; use api::egl::Context as EglContext; +use platform::MonitorId as PlatformMonitorId; +use wayland_client::EventIterator; use wayland_client::egl as wegl; +use wayland_client::wayland::shell::WlShellSurface; use super::wayland_window::{DecoratedSurface, add_borders, substract_borders}; use super::context::{WaylandContext, WAYLAND_CONTEXT}; @@ -27,7 +30,7 @@ impl WindowProxy { pub struct Window { wayland_context: &'static WaylandContext, egl_surface: wegl::WlEglSurface, - decorated_surface: Mutex, + shell_window: Mutex, evt_queue: Arc>>, inner_size: Mutex<(i32, i32)>, resize_callback: Option, @@ -36,21 +39,50 @@ pub struct Window { impl Window { fn next_event(&self) -> Option { + use wayland_client::Event as WEvent; + use wayland_client::wayland::WaylandProtocolEvent; + use wayland_client::wayland::shell::WlShellSurfaceEvent; + let mut newsize = None; - for (_, w, h) in &mut *self.decorated_surface.lock().unwrap() { - newsize = Some((w, h)); + let mut evt_queue_guard = self.evt_queue.lock().unwrap(); + + let mut shell_window_guard = self.shell_window.lock().unwrap(); + match *shell_window_guard { + ShellWindow::Decorated(ref mut deco) => { + for (_, w, h) in deco { + newsize = Some((w, h)); + } + }, + ShellWindow::Plain(ref plain, ref mut evtiter) => { + for evt in evtiter { + if let WEvent::Wayland(WaylandProtocolEvent::WlShellSurface(_, ssevt)) = evt { + match ssevt { + WlShellSurfaceEvent::Ping(u) => { + plain.pong(u); + }, + WlShellSurfaceEvent::Configure(_, w, h) => { + newsize = Some((w, h)); + }, + _ => {} + } + } + } + } } + if let Some((w, h)) = newsize { let (w, h) = substract_borders(w, h); *self.inner_size.lock().unwrap() = (w, h); - self.decorated_surface.lock().unwrap().resize(w, h); + if let ShellWindow::Decorated(ref mut deco) = *shell_window_guard { + deco.resize(w, h); + } self.egl_surface.resize(w, h, 0, 0); if let Some(f) = self.resize_callback { f(w as u32, h as u32); } Some(Event::Resized(w as u32, h as u32)) } else { - self.evt_queue.lock().unwrap().pop_front() + evt_queue_guard.pop_front() } } } @@ -99,10 +131,16 @@ impl<'a> Iterator for WaitEventsIterator<'a> { } } +enum ShellWindow { + Plain(WlShellSurface, EventIterator), + Decorated(DecoratedSurface) +} + impl Window { pub fn new(window: &WindowAttributes, pf_reqs: &PixelFormatRequirements, opengl: &GlAttributes<&Window>) -> Result { + use wayland_client::Proxy; // not implemented assert!(window.min_dimensions.is_none()); assert!(window.max_dimensions.is_none()); @@ -142,15 +180,36 @@ impl Window { ) }; - let decorated_surface = match wayland_context.decorated_from(&egl_surface, w as i32, h as i32) { - Some(s) => s, - None => return Err(CreationError::NotSupported) + let shell_window = if let Some(PlatformMonitorId::Wayland(ref monitor_id)) = window.monitor { + let pid = super::monitor::proxid_from_monitorid(monitor_id); + match wayland_context.plain_from(&egl_surface, Some(pid)) { + Some(mut s) => { + let iter = EventIterator::new(); + s.set_evt_iterator(&iter); + ShellWindow::Plain(s, iter) + }, + None => return Err(CreationError::NotSupported) + } + } else if window.decorations { + match wayland_context.decorated_from(&egl_surface, w as i32, h as i32) { + Some(s) => ShellWindow::Decorated(s), + None => return Err(CreationError::NotSupported) + } + } else { + match wayland_context.plain_from(&egl_surface, None) { + Some(mut s) => { + let iter = EventIterator::new(); + s.set_evt_iterator(&iter); + ShellWindow::Plain(s, iter) + }, + None => return Err(CreationError::NotSupported) + } }; Ok(Window { wayland_context: wayland_context, egl_surface: egl_surface, - decorated_surface: Mutex::new(decorated_surface), + shell_window: Mutex::new(shell_window), evt_queue: evt_queue, inner_size: Mutex::new((w as i32, h as i32)), resize_callback: None, @@ -159,7 +218,11 @@ impl Window { } pub fn set_title(&self, title: &str) { - self.decorated_surface.lock().unwrap().set_title(title.into()) + let guard = self.shell_window.lock().unwrap(); + match *guard { + ShellWindow::Plain(ref plain, _) => { plain.set_title(title.into()); }, + ShellWindow::Decorated(ref deco) => { deco.set_title(title.into()); } + } } #[inline] @@ -197,7 +260,12 @@ impl Window { #[inline] pub fn set_inner_size(&self, x: u32, y: u32) { - self.decorated_surface.lock().unwrap().resize(x as i32, y as i32) + let mut guard = self.shell_window.lock().unwrap(); + match *guard { + ShellWindow::Decorated(ref mut deco) => { deco.resize(x as i32, y as i32); }, + _ => {} + } + self.egl_surface.resize(x as i32, y as i32, 0, 0) } #[inline] -- cgit v1.2.3 From 6eba737fce8f50798d81c24eb70872ff46a2da3a Mon Sep 17 00:00:00 2001 From: Victor Berger Date: Tue, 22 Dec 2015 14:35:55 +0100 Subject: api/wayland: fix cursor errors --- src/api/wayland/events.rs | 3 ++- src/api/wayland/window.rs | 13 +++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) (limited to 'src/api/wayland/window.rs') diff --git a/src/api/wayland/events.rs b/src/api/wayland/events.rs index 8aeddac..8b18020 100644 --- a/src/api/wayland/events.rs +++ b/src/api/wayland/events.rs @@ -21,7 +21,8 @@ pub fn translate_event( focuses: &mut WaylandFocuses, known_surfaces: &HashSet, seat: Option<&WlSeat>, -) -> Option<(GlutinEvent, ProxyId)> { + ) -> Option<(GlutinEvent, ProxyId)> +{ let WaylandEvent::Wayland(wayland_evt) = evt; match wayland_evt { WPE::WlSeat(_, seat_evt) => match seat_evt { diff --git a/src/api/wayland/window.rs b/src/api/wayland/window.rs index a9285fa..0005a83 100644 --- a/src/api/wayland/window.rs +++ b/src/api/wayland/window.rs @@ -298,9 +298,14 @@ impl Window { } #[inline] - pub fn set_cursor_state(&self, _state: CursorState) -> Result<(), String> { - // TODO - Ok(()) + pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> { + use CursorState::{Grab, Normal, Hide}; + // TODO : not yet possible on wayland to grab cursor + match state { + Grab => Err("Cursor cannot be grabbed on wayland yet.".to_string()), + Hide => Err("Cursor cannot be hidden on wayland yet.".to_string()), + Normal => Ok(()) + } } #[inline] @@ -311,7 +316,7 @@ impl Window { #[inline] pub fn set_cursor_position(&self, _x: i32, _y: i32) -> Result<(), ()> { // TODO: not yet possible on wayland - Ok(()) + Err(()) } #[inline] -- cgit v1.2.3