Merge pull request #199 from alexheretic/xwayland-env-var

Add a `WINIT_UNIX_BACKEND` environment variable to all the user to control the choice of x11/wayland backend.
This commit is contained in:
Victor Berger 2017-06-25 10:40:05 +02:00 committed by GitHub
commit 05cd9f2114
3 changed files with 71 additions and 14 deletions

View file

@ -1,4 +1,4 @@
//! Winit allows you to build a window on as many platforms as possible.
//! Winit allows you to build a window on as many platforms as possible.
//!
//! # Building a window
//!
@ -181,6 +181,14 @@ pub struct ButtonId(u32);
/// Provides a way to retreive events from the windows that were registered to it.
///
/// To wake up an `EventsLoop` from a another thread, see the `EventsLoopProxy` docs.
///
/// Usage will result in display backend initialisation, this can be controlled on linux
/// using an environment variable `WINIT_UNIX_BACKEND`.
/// > Legal values are `x11` and `wayland`. If this variable is set only the named backend
/// > will be tried by winit. If it is not set, winit will try to connect to a wayland connection,
/// > and if it fails will fallback on x11.
/// >
/// > If this variable is set with any other value, winit will panic.
pub struct EventsLoop {
events_loop: platform::EventsLoop,
}

View file

@ -2,6 +2,7 @@
use std::collections::VecDeque;
use std::sync::Arc;
use std::env;
use {CreationError, CursorState, EventsLoopClosed, MouseCursor, ControlFlow};
use libc;
@ -15,6 +16,15 @@ mod dlopen;
pub mod wayland;
pub mod x11;
/// Environment variable specifying which backend should be used on unix platform.
///
/// Legal values are x11 and wayland. If this variable is set only the named backend
/// will be tried by winit. If it is not set, winit will try to connect to a wayland connection,
/// and if it fails will fallback on x11.
///
/// If this variable is set with any other value, winit will panic.
const BACKEND_PREFERENCE_ENV_VAR: &str = "WINIT_UNIX_BACKEND";
#[derive(Clone, Default)]
pub struct PlatformSpecificWindowBuilderAttributes {
pub visual_infos: Option<XVisualInfo>,
@ -24,19 +34,42 @@ pub struct PlatformSpecificWindowBuilderAttributes {
pub enum UnixBackend {
X(Arc<XConnection>),
Wayland(Arc<wayland::WaylandContext>),
Error(XNotSupported),
}
Error(Option<XNotSupported>, Option<String>),
}
lazy_static!(
pub static ref UNIX_BACKEND: UnixBackend = {
if let Some(ctxt) = wayland::WaylandContext::init() {
UnixBackend::Wayland(Arc::new(ctxt))
} else {
#[inline]
fn x_backend() -> Result<UnixBackend, XNotSupported> {
match XConnection::new(Some(x_error_callback)) {
Ok(x) => UnixBackend::X(Arc::new(x)),
Err(e) => UnixBackend::Error(e),
Ok(x) => Ok(UnixBackend::X(Arc::new(x))),
Err(e) => Err(e),
}
}
#[inline]
fn wayland_backend() -> Result<UnixBackend, ()> {
wayland::WaylandContext::init()
.map(|ctx| UnixBackend::Wayland(Arc::new(ctx)))
.ok_or(())
}
match env::var(BACKEND_PREFERENCE_ENV_VAR) {
Ok(s) => match s.as_str() {
"x11" => x_backend().unwrap_or_else(|e| UnixBackend::Error(Some(e), None)),
"wayland" => wayland_backend().unwrap_or_else(|_| {
UnixBackend::Error(None, Some("Wayland not available".into()))
}),
_ => panic!("Unknown environment variable value for {}, try one of `x11`,`wayland`",
BACKEND_PREFERENCE_ENV_VAR),
},
Err(_) => {
// Try wayland, fallback to X11
wayland_backend().unwrap_or_else(|_| {
x_backend().unwrap_or_else(|x_err| {
UnixBackend::Error(Some(x_err), Some("Wayland not available".into()))
})
})
},
}
};
);
@ -85,7 +118,7 @@ pub fn get_available_monitors() -> VecDeque<MonitorId> {
.into_iter()
.map(MonitorId::X)
.collect(),
UnixBackend::Error(_) => { let mut d = VecDeque::new(); d.push_back(MonitorId::None); d},
UnixBackend::Error(..) => { let mut d = VecDeque::new(); d.push_back(MonitorId::None); d},
}
}
@ -94,7 +127,7 @@ pub fn get_primary_monitor() -> MonitorId {
match *UNIX_BACKEND {
UnixBackend::Wayland(ref ctxt) => MonitorId::Wayland(wayland::get_primary_monitor(ctxt)),
UnixBackend::X(ref connec) => MonitorId::X(x11::get_primary_monitor(connec)),
UnixBackend::Error(_) => MonitorId::None,
UnixBackend::Error(..) => MonitorId::None,
}
}
@ -147,7 +180,7 @@ impl Window2 {
UnixBackend::X(_) => {
x11::Window2::new(events_loop, window, pl_attribs).map(Window2::X)
},
UnixBackend::Error(_) => {
UnixBackend::Error(..) => {
// If the Backend is Error(), it is not possible to instanciate an EventsLoop at all,
// thus this function cannot be called!
unreachable!()
@ -324,7 +357,7 @@ impl EventsLoop {
EventsLoop::X(x11::EventsLoop::new(ctxt.clone()))
},
UnixBackend::Error(_) => {
UnixBackend::Error(..) => {
panic!("Attempted to create an EventsLoop while no backend was available.")
}
}

View file

@ -30,7 +30,7 @@ impl WindowBuilder {
self.window.dimensions = Some((width, height));
self
}
/// Sets a minimum dimension size for the window
///
/// Width and height are in pixels.
@ -197,7 +197,7 @@ impl Window {
pub fn get_inner_size(&self) -> Option<(u32, u32)> {
self.window.get_inner_size()
}
/// Returns the size in points of the client area of the window.
///
/// The client area is the content of the window, excluding the title bar and borders.
@ -320,6 +320,14 @@ impl Iterator for AvailableMonitorsIter {
}
/// Returns the list of all available monitors.
///
/// Usage will result in display backend initialisation, this can be controlled on linux
/// using an environment variable `WINIT_UNIX_BACKEND`.
/// > Legal values are `x11` and `wayland`. If this variable is set only the named backend
/// > will be tried by winit. If it is not set, winit will try to connect to a wayland connection,
/// > and if it fails will fallback on x11.
/// >
/// > If this variable is set with any other value, winit will panic.
#[inline]
pub fn get_available_monitors() -> AvailableMonitorsIter {
let data = platform::get_available_monitors();
@ -327,6 +335,14 @@ pub fn get_available_monitors() -> AvailableMonitorsIter {
}
/// Returns the primary monitor of the system.
///
/// Usage will result in display backend initialisation, this can be controlled on linux
/// using an environment variable `WINIT_UNIX_BACKEND`.
/// > Legal values are `x11` and `wayland`. If this variable is set only the named backend
/// > will be tried by winit. If it is not set, winit will try to connect to a wayland connection,
/// > and if it fails will fallback on x11.
/// >
/// > If this variable is set with any other value, winit will panic.
#[inline]
pub fn get_primary_monitor() -> MonitorId {
MonitorId(platform::get_primary_monitor())