From 1278d9779d119be706d75d1ecaeaa9846fd78ed2 Mon Sep 17 00:00:00 2001 From: Victor Berger Date: Sat, 9 May 2015 22:30:17 +0200 Subject: [PATCH 1/4] wayland: Fix MonitorID::get_dimensions() and fullscreen support. --- src/api/wayland/mod.rs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/api/wayland/mod.rs b/src/api/wayland/mod.rs index 4fd0357c..68385988 100644 --- a/src/api/wayland/mod.rs +++ b/src/api/wayland/mod.rs @@ -4,7 +4,7 @@ use self::wayland::egl::{EGLSurface, is_egl_available}; use self::wayland::core::{Display, Registry, Compositor, Shell, ShellSurface, Seat, Pointer, default_display, WSurface, SurfaceId, - Surface, Output}; + Surface, Output, ShellFullscreenMethod}; use libc; use api::dlopen; @@ -172,6 +172,7 @@ impl WindowProxy { } } +#[derive(Clone)] pub struct MonitorID { output: Arc } @@ -202,7 +203,11 @@ impl MonitorID { } pub fn get_dimensions(&self) -> (u32, u32) { - let (w, h) = self.output.dimensions(); + let (w, h) = self.output.modes() + .into_iter() + .find(|m| m.is_current()) + .map(|m| (m.width, m.height)) + .unwrap(); (w as u32, h as u32) } } @@ -257,6 +262,13 @@ impl Window { h as i32 ); + let shell_surface = wayland_context.shell.get_shell_surface(surface); + if let Some(ref monitor) = builder.monitor { + shell_surface.set_fullscreen(ShellFullscreenMethod::Default, Some(&monitor.output)); + } else { + shell_surface.set_toplevel(); + } + let context = { let libegl = unsafe { dlopen::dlopen(b"libEGL.so\0".as_ptr() as *const _, dlopen::RTLD_NOW) }; if libegl.is_null() { @@ -270,12 +282,10 @@ impl Window { egl, builder, Some(wayland_context.display.ptr() as *const _), - surface.ptr() as *const _ + (*shell_surface).ptr() as *const _ )) }; - let shell_surface = wayland_context.shell.get_shell_surface(surface); - shell_surface.set_toplevel(); let events = Arc::new(Mutex::new(VecDeque::new())); wayland_context.register_surface(shell_surface.get_wsurface().get_id(), events.clone()); From 40322a2c69bdbb465ce1481aa61ac6dec85e10dd Mon Sep 17 00:00:00 2001 From: Victor Berger Date: Sun, 10 May 2015 19:13:56 +0200 Subject: [PATCH 2/4] Implement some more functions for wayland. - set/get_inner_size() - set_title --- Cargo.toml | 6 +++--- src/api/wayland/mod.rs | 34 +++++++++++++++++++++++++--------- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 32e8d901..89ed55e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,15 +50,15 @@ kernel32-sys = "0.1" [target.i686-unknown-linux-gnu.dependencies] osmesa-sys = "0.0.5" -wayland-client = "0.1.4" +wayland-client = "0.1.5" x11-dl = "=1.0.1" [target.x86_64-unknown-linux-gnu.dependencies] osmesa-sys = "0.0.5" -wayland-client = "0.1.4" +wayland-client = "0.1.5" x11-dl = "=1.0.1" [target.arm-unknown-linux-gnueabihf.dependencies] osmesa-sys = "0.0.5" -wayland-client = "0.1.4" +wayland-client = "0.1.5" x11-dl = "=1.0.1" diff --git a/src/api/wayland/mod.rs b/src/api/wayland/mod.rs index 68385988..1c6c0e7b 100644 --- a/src/api/wayland/mod.rs +++ b/src/api/wayland/mod.rs @@ -157,10 +157,6 @@ pub struct Window { pub context: EglContext, } -// It is okay, as the window is completely self-owned: it has its -// own wayland connexion. -unsafe impl Send for Window {} - #[derive(Clone)] pub struct WindowProxy; @@ -300,16 +296,21 @@ impl Window { } pub fn is_closed(&self) -> bool { + // TODO false } pub fn set_title(&self, title: &str) { + let ctitle = CString::new(title).unwrap(); + self.shell_surface.set_title(&ctitle); } pub fn show(&self) { + // TODO } pub fn hide(&self) { + // TODO } pub fn get_position(&self) -> Option<(i32, i32)> { @@ -322,15 +323,18 @@ impl Window { } pub fn get_inner_size(&self) -> Option<(u32, u32)> { - unimplemented!() + let (w, h) = self.shell_surface.get_attached_size(); + Some((w as u32, h as u32)) } pub fn get_outer_size(&self) -> Option<(u32, u32)> { - unimplemented!() + // maybe available if we draw the border ourselves ? + // but for now, no. + None } - pub fn set_inner_size(&self, _x: u32, _y: u32) { - unimplemented!() + pub fn set_inner_size(&self, x: u32, y: u32) { + self.shell_surface.resize(x as i32, y as i32, 0, 0) } pub fn create_window_proxy(&self) -> WindowProxy { @@ -349,13 +353,24 @@ impl Window { } } - pub fn set_window_resize_callback(&mut self, _: Option) { + pub fn set_window_resize_callback(&mut self, callback: Option) { + if let Some(callback) = callback { + self.shell_surface.set_configure_callback( + move |_,w,h| { callback(w as u32, h as u32) } + ); + } else { + self.shell_surface.set_configure_callback( + move |_,_,_| {} + ); + } } pub fn set_cursor(&self, cursor: MouseCursor) { + // TODO } pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> { + // TODO Ok(()) } @@ -364,6 +379,7 @@ impl Window { } pub fn set_cursor_position(&self, x: i32, y: i32) -> Result<(), ()> { + // TODO Ok(()) } From 562d6cd1e3c3d0c2e9b0f11b2e21ca06214acd41 Mon Sep 17 00:00:00 2001 From: Victor Berger Date: Sun, 10 May 2015 19:30:57 +0200 Subject: [PATCH 3/4] Move WaylandContext in its own file. --- src/api/wayland/context.rs | 124 ++++++++++++++++++++++++++++++++++++ src/api/wayland/mod.rs | 125 ++----------------------------------- 2 files changed, 129 insertions(+), 120 deletions(-) create mode 100644 src/api/wayland/context.rs diff --git a/src/api/wayland/context.rs b/src/api/wayland/context.rs new file mode 100644 index 00000000..44a1f518 --- /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 diff --git a/src/api/wayland/mod.rs b/src/api/wayland/mod.rs index 1c6c0e7b..7a53abe2 100644 --- a/src/api/wayland/mod.rs +++ b/src/api/wayland/mod.rs @@ -2,9 +2,7 @@ #![allow(unused_variables, dead_code)] use self::wayland::egl::{EGLSurface, is_egl_available}; -use self::wayland::core::{Display, Registry, Compositor, Shell, ShellSurface, - Seat, Pointer, default_display, WSurface, SurfaceId, - Surface, Output, ShellFullscreenMethod}; +use self::wayland::core::{ShellSurface, Surface, Output, ShellFullscreenMethod}; use libc; use api::dlopen; @@ -18,128 +16,15 @@ use CursorState; use MouseCursor; use GlContext; -use std::collections::{VecDeque, HashMap}; +use std::collections::VecDeque; use std::sync::{Arc, Mutex}; use std::ffi::CString; +use self::context::WaylandContext; + extern crate wayland_client as wayland; -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>>, - 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 self::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 - }) - } - - fn register_surface(&self, sid: SurfaceId, queue: Arc>>) { - self.windows_event_queues.lock().unwrap().insert(sid, queue); - } - - fn deregister_surface(&self, sid: SurfaceId) { - self.windows_event_queues.lock().unwrap().remove(&sid); - } -} +mod context; lazy_static! { static ref WAYLAND_CONTEXT: Option = { From 9e489fee01da22eb1ff029e14544270cc0360fdd Mon Sep 17 00:00:00 2001 From: Victor Berger Date: Wed, 13 May 2015 08:32:20 +0200 Subject: [PATCH 4/4] Update to new Platform structure. --- src/api/wayland/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/api/wayland/mod.rs b/src/api/wayland/mod.rs index 7a53abe2..569f93f9 100644 --- a/src/api/wayland/mod.rs +++ b/src/api/wayland/mod.rs @@ -20,6 +20,8 @@ use std::collections::VecDeque; use std::sync::{Arc, Mutex}; use std::ffi::CString; +use platform::MonitorID as PlatformMonitorID; + use self::context::WaylandContext; extern crate wayland_client as wayland; @@ -144,7 +146,7 @@ impl Window { ); let shell_surface = wayland_context.shell.get_shell_surface(surface); - if let Some(ref monitor) = builder.monitor { + if let Some(PlatformMonitorID::Wayland(ref monitor)) = builder.monitor { shell_surface.set_fullscreen(ShellFullscreenMethod::Default, Some(&monitor.output)); } else { shell_surface.set_toplevel();