Merge branch 'master' of https://github.com/tomaka/winit into xim-send-spot

This commit is contained in:
Determinant 2017-07-12 00:04:12 -04:00
commit f2ee78bcf5
16 changed files with 1329 additions and 1132 deletions

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

@ -7,7 +7,7 @@ use std::sync::atomic::{self, AtomicBool};
use super::{DecoratedHandler, WindowId, DeviceId, WaylandContext};
use wayland_client::{EventQueue, EventQueueHandle, Init, Proxy};
use wayland_client::{EventQueue, EventQueueHandle, Init, Proxy, Liveness};
use wayland_client::protocol::{wl_seat, wl_surface, wl_pointer, wl_keyboard};
use super::make_wid;
@ -159,13 +159,13 @@ impl EventsLoop {
}
fn prune_dead_windows(&self) {
self.decorated_ids.lock().unwrap().retain(|&(_, ref w)| w.is_alive());
self.decorated_ids.lock().unwrap().retain(|&(_, ref w)| w.status() == Liveness::Alive);
let mut evq_guard = self.evq.lock().unwrap();
let mut state = evq_guard.state();
let handler = state.get_mut_handler::<InputHandler>(self.hid);
handler.windows.retain(|w| w.is_alive());
handler.windows.retain(|w| w.status() == Liveness::Alive);
if let Some(w) = handler.mouse_focus.take() {
if w.is_alive() {
if w.status() == Liveness::Alive {
handler.mouse_focus = Some(w)
}
}