From 310b44f35be8146623d8e5fbbe380ae14f30de72 Mon Sep 17 00:00:00 2001 From: Victor Berger Date: Tue, 12 May 2015 22:47:34 +0200 Subject: Make platform::linux generic over X11 and Wayland. --- src/platform/linux/api_dispatch.rs | 324 +++++++++++++++++++++++++++++++++++++ src/platform/linux/mod.rs | 6 +- 2 files changed, 328 insertions(+), 2 deletions(-) create mode 100644 src/platform/linux/api_dispatch.rs (limited to 'src/platform/linux') diff --git a/src/platform/linux/api_dispatch.rs b/src/platform/linux/api_dispatch.rs new file mode 100644 index 0000000..c77c464 --- /dev/null +++ b/src/platform/linux/api_dispatch.rs @@ -0,0 +1,324 @@ +/*#[cfg(feature = "window")] +pub use api::x11::{Window, WindowProxy, MonitorID, get_available_monitors, get_primary_monitor}; +#[cfg(feature = "window")] +pub use api::x11::{WaitEventsIterator, PollEventsIterator};*/ + +use std::collections::VecDeque; + +use BuilderAttribs; +use CreationError; +use CursorState; +use Event; +use GlContext; +use MouseCursor; +use PixelFormat; +use libc; + +use api::wayland; +use api::x11; + +pub enum Window { + #[doc(hidden)] + X(x11::Window), + #[doc(hidden)] + Wayland(wayland::Window) +} + +#[derive(Clone)] +pub enum WindowProxy { + #[doc(hidden)] + X(x11::WindowProxy), + #[doc(hidden)] + Wayland(wayland::WindowProxy) +} + +impl WindowProxy { + pub fn wakeup_event_loop(&self) { + match self { + &WindowProxy::X(ref wp) => wp.wakeup_event_loop(), + &WindowProxy::Wayland(ref wp) => wp.wakeup_event_loop() + } + } +} + +pub enum MonitorID { + #[doc(hidden)] + X(x11::MonitorID), + #[doc(hidden)] + Wayland(wayland::MonitorID) +} + +pub fn get_available_monitors() -> VecDeque { + if wayland::is_available() { + // We are doing wayland + wayland::get_available_monitors() + .into_iter() + .map(|m| MonitorID::Wayland(m)) + .collect() + } else { + // Fallback on X + x11::get_available_monitors() + .into_iter() + .map(|m| MonitorID::X(m)) + .collect() + } +} +pub fn get_primary_monitor() -> MonitorID { + if wayland::is_available() { + MonitorID::Wayland(wayland::get_primary_monitor()) + } else { + MonitorID::X(x11::get_primary_monitor()) + } +} + +impl MonitorID { + pub fn get_name(&self) -> Option { + match self { + &MonitorID::X(ref m) => m.get_name(), + &MonitorID::Wayland(ref m) => m.get_name() + } + } + + pub fn get_native_identifier(&self) -> ::native_monitor::NativeMonitorId { + match self { + &MonitorID::X(ref m) => m.get_native_identifier(), + &MonitorID::Wayland(ref m) => m.get_native_identifier() + } + } + + pub fn get_dimensions(&self) -> (u32, u32) { + match self { + &MonitorID::X(ref m) => m.get_dimensions(), + &MonitorID::Wayland(ref m) => m.get_dimensions() + } + } +} + + +pub enum PollEventsIterator<'a> { + #[doc(hidden)] + X(x11::PollEventsIterator<'a>), + #[doc(hidden)] + Wayland(wayland::PollEventsIterator<'a>) +} + +impl<'a> Iterator for PollEventsIterator<'a> { + type Item = Event; + + fn next(&mut self) -> Option { + match self { + &mut PollEventsIterator::X(ref mut it) => it.next(), + &mut PollEventsIterator::Wayland(ref mut it) => it.next() + } + } +} + +pub enum WaitEventsIterator<'a> { + #[doc(hidden)] + X(x11::WaitEventsIterator<'a>), + #[doc(hidden)] + Wayland(wayland::WaitEventsIterator<'a>) +} + +impl<'a> Iterator for WaitEventsIterator<'a> { + type Item = Event; + + fn next(&mut self) -> Option { + match self { + &mut WaitEventsIterator::X(ref mut it) => it.next(), + &mut WaitEventsIterator::Wayland(ref mut it) => it.next() + } + } +} + +impl Window { + pub fn new(builder: BuilderAttribs) -> Result { + if wayland::is_available() { + // we have a wayland connection, go for it + let window = try!(wayland::Window::new(builder)); + Ok(Window::Wayland(window)) + } else { + // fallback on X + let window = try!(x11::Window::new(builder)); + Ok(Window::X(window)) + } + } + + pub fn is_closed(&self) -> bool { + match self { + &Window::X(ref w) => w.is_closed(), + &Window::Wayland(ref w) => w.is_closed() + } + } + + pub fn set_title(&self, title: &str) { + match self { + &Window::X(ref w) => w.set_title(title), + &Window::Wayland(ref w) => w.set_title(title) + } + } + + pub fn show(&self) { + match self { + &Window::X(ref w) => w.show(), + &Window::Wayland(ref w) => w.show() + } + } + + pub fn hide(&self) { + match self { + &Window::X(ref w) => w.hide(), + &Window::Wayland(ref w) => w.hide() + } + } + + pub fn get_position(&self) -> Option<(i32, i32)> { + match self { + &Window::X(ref w) => w.get_position(), + &Window::Wayland(ref w) => w.get_position() + } + } + + pub fn set_position(&self, x: i32, y: i32) { + match self { + &Window::X(ref w) => w.set_position(x, y), + &Window::Wayland(ref w) => w.set_position(x, y) + } + } + + pub fn get_inner_size(&self) -> Option<(u32, u32)> { + match self { + &Window::X(ref w) => w.get_inner_size(), + &Window::Wayland(ref w) => w.get_inner_size() + } + } + + pub fn get_outer_size(&self) -> Option<(u32, u32)> { + match self { + &Window::X(ref w) => w.get_outer_size(), + &Window::Wayland(ref w) => w.get_outer_size() + } + } + + pub fn set_inner_size(&self, x: u32, y: u32) { + match self { + &Window::X(ref w) => w.set_inner_size(x, y), + &Window::Wayland(ref w) => w.set_inner_size(x, y) + } + } + + pub fn create_window_proxy(&self) -> WindowProxy { + match self { + &Window::X(ref w) => WindowProxy::X(w.create_window_proxy()), + &Window::Wayland(ref w) => WindowProxy::Wayland(w.create_window_proxy()) + } + } + + pub fn poll_events(&self) -> PollEventsIterator { + match self { + &Window::X(ref w) => PollEventsIterator::X(w.poll_events()), + &Window::Wayland(ref w) => PollEventsIterator::Wayland(w.poll_events()) + } + } + + pub fn wait_events(&self) -> WaitEventsIterator { + match self { + &Window::X(ref w) => WaitEventsIterator::X(w.wait_events()), + &Window::Wayland(ref w) => WaitEventsIterator::Wayland(w.wait_events()) + } + } + + pub fn set_window_resize_callback(&mut self, callback: Option) { + match self { + &mut Window::X(ref mut w) => w.set_window_resize_callback(callback), + &mut Window::Wayland(ref mut w) => w.set_window_resize_callback(callback) + } + } + + pub fn set_cursor(&self, cursor: MouseCursor) { + match self { + &Window::X(ref w) => w.set_cursor(cursor), + &Window::Wayland(ref w) => w.set_cursor(cursor) + } + } + + pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> { + match self { + &Window::X(ref w) => w.set_cursor_state(state), + &Window::Wayland(ref w) => w.set_cursor_state(state) + } + } + + pub fn hidpi_factor(&self) -> f32 { + match self { + &Window::X(ref w) => w.hidpi_factor(), + &Window::Wayland(ref w) => w.hidpi_factor() + } + } + + pub fn set_cursor_position(&self, x: i32, y: i32) -> Result<(), ()> { + match self { + &Window::X(ref w) => w.set_cursor_position(x, y), + &Window::Wayland(ref w) => w.set_cursor_position(x, y) + } + } + + pub fn platform_display(&self) -> *mut libc::c_void { + match self { + &Window::X(ref w) => w.platform_display(), + &Window::Wayland(ref w) => w.platform_display() + } + } + + pub fn platform_window(&self) -> *mut libc::c_void { + match self { + &Window::X(ref w) => w.platform_window(), + &Window::Wayland(ref w) => w.platform_window() + } + } +} + +impl GlContext for Window { + + unsafe fn make_current(&self) { + match self { + &Window::X(ref w) => w.make_current(), + &Window::Wayland(ref w) => w.make_current() + } + } + + fn is_current(&self) -> bool { + match self { + &Window::X(ref w) => w.is_current(), + &Window::Wayland(ref w) => w.is_current() + } + } + + fn get_proc_address(&self, addr: &str) -> *const libc::c_void { + match self { + &Window::X(ref w) => w.get_proc_address(addr), + &Window::Wayland(ref w) => w.get_proc_address(addr) + } + } + + fn swap_buffers(&self) { + match self { + &Window::X(ref w) => w.swap_buffers(), + &Window::Wayland(ref w) => w.swap_buffers() + } + } + + fn get_api(&self) -> ::Api { + match self { + &Window::X(ref w) => w.get_api(), + &Window::Wayland(ref w) => w.get_api() + } + } + + fn get_pixel_format(&self) -> PixelFormat { + match self { + &Window::X(ref w) => w.get_pixel_format(), + &Window::Wayland(ref w) => w.get_pixel_format() + } + } +} \ No newline at end of file diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs index 1e12a80..323a21a 100644 --- a/src/platform/linux/mod.rs +++ b/src/platform/linux/mod.rs @@ -10,9 +10,11 @@ use libc; use api::osmesa::{self, OsMesaContext}; #[cfg(feature = "window")] -pub use api::x11::{Window, WindowProxy, MonitorID, get_available_monitors, get_primary_monitor}; +pub use self::api_dispatch::{Window, WindowProxy, MonitorID, get_available_monitors, get_primary_monitor}; #[cfg(feature = "window")] -pub use api::x11::{WaitEventsIterator, PollEventsIterator}; +pub use self::api_dispatch::{WaitEventsIterator, PollEventsIterator}; +#[cfg(feature = "window")] +mod api_dispatch; #[cfg(not(feature = "window"))] pub type Window = (); // TODO: hack to make things work -- cgit v1.2.3