wayland: mugrate to new API

This commit is contained in:
Victor Berger 2017-03-04 14:04:01 +01:00
parent 9aaa788434
commit 7336cacf07
6 changed files with 310 additions and 305 deletions

View file

@ -129,7 +129,12 @@ impl Window2 {
{ {
match *UNIX_BACKEND { match *UNIX_BACKEND {
UnixBackend::Wayland(ref ctxt) => { UnixBackend::Wayland(ref ctxt) => {
wayland::Window2::new(events_loop, ctxt.clone(), window).map(Window2::Wayland) if let EventsLoop::Wayland(ref evlp) = *events_loop {
wayland::Window2::new(evlp, ctxt.clone(), window).map(Window2::Wayland)
} else {
// It is not possible to instanciate an EventsLoop not matching its backend
unreachable!()
}
}, },
UnixBackend::X(ref connec) => { UnixBackend::X(ref connec) => {
@ -299,8 +304,8 @@ pub enum EventsLoop {
impl EventsLoop { impl EventsLoop {
pub fn new() -> EventsLoop { pub fn new() -> EventsLoop {
match *UNIX_BACKEND { match *UNIX_BACKEND {
UnixBackend::Wayland(_) => { UnixBackend::Wayland(ref ctxt) => {
EventsLoop::Wayland(wayland::EventsLoop::new()) EventsLoop::Wayland(wayland::EventsLoop::new(ctxt.clone()))
}, },
UnixBackend::X(_) => { UnixBackend::X(_) => {

View file

@ -10,7 +10,7 @@ use wayland_client::protocol::{wl_compositor, wl_seat, wl_shell, wl_shm, wl_subc
wl_display, wl_registry, wl_output, wl_surface, wl_pointer, wl_display, wl_registry, wl_output, wl_surface, wl_pointer,
wl_keyboard}; wl_keyboard};
use super::wayland_window; use super::{wayland_window, EventsLoopSink, make_wid};
use super::wayland_kbd::MappedKeyboard; use super::wayland_kbd::MappedKeyboard;
use super::keyboard::KbdHandler; use super::keyboard::KbdHandler;
@ -27,7 +27,7 @@ wayland_env!(InnerEnv,
enum KbdType { enum KbdType {
Mapped(MappedKeyboard<KbdHandler>), Mapped(MappedKeyboard<KbdHandler>),
Plain(Option<Arc<Mutex<VecDeque<Event>>>>) Plain(Option<(Arc<wl_surface::WlSurface>,Arc<Mutex<EventsLoopSink>>)>)
} }
struct WaylandEnv { struct WaylandEnv {
@ -35,10 +35,10 @@ struct WaylandEnv {
inner: EnvHandler<InnerEnv>, inner: EnvHandler<InnerEnv>,
monitors: Vec<OutputInfo>, monitors: Vec<OutputInfo>,
my_id: usize, my_id: usize,
windows: Vec<(Arc<wl_surface::WlSurface>,Arc<Mutex<VecDeque<Event>>>)>, windows: Vec<(Arc<wl_surface::WlSurface>,Arc<Mutex<EventsLoopSink>>)>,
seat: Option<wl_seat::WlSeat>, seat: Option<wl_seat::WlSeat>,
mouse: Option<wl_pointer::WlPointer>, mouse: Option<wl_pointer::WlPointer>,
mouse_focus: Option<Arc<Mutex<VecDeque<Event>>>>, mouse_focus: Option<(Arc<wl_surface::WlSurface>,Arc<Mutex<EventsLoopSink>>)>,
mouse_location: (i32, i32), mouse_location: (i32, i32),
axis_buffer: Option<(f32, f32)>, axis_buffer: Option<(f32, f32)>,
axis_discrete_buffer: Option<(i32, i32)>, axis_discrete_buffer: Option<(i32, i32)>,
@ -252,16 +252,15 @@ impl WaylandContext {
} }
} }
pub fn create_window<H: wayland_window::Handler>(&self) pub fn create_window<H: wayland_window::Handler>(&self, sink: Arc<Mutex<EventsLoopSink>>)
-> (Arc<wl_surface::WlSurface>, Arc<Mutex<VecDeque<Event>>>, wayland_window::DecoratedSurface<H>) -> (Arc<wl_surface::WlSurface>, wayland_window::DecoratedSurface<H>)
{ {
let mut guard = self.evq.lock().unwrap(); let mut guard = self.evq.lock().unwrap();
let mut state = guard.state(); let mut state = guard.state();
let env = state.get_mut_handler::<WaylandEnv>(self.env_id); let env = state.get_mut_handler::<WaylandEnv>(self.env_id);
// this "expect" cannot trigger (see https://github.com/vberger/wayland-client-rs/issues/69) // this "expect" cannot trigger (see https://github.com/vberger/wayland-client-rs/issues/69)
let surface = Arc::new(env.inner.compositor.create_surface().expect("Compositor cannot be dead")); let surface = Arc::new(env.inner.compositor.create_surface().expect("Compositor cannot be dead"));
let eventiter = Arc::new(Mutex::new(VecDeque::new())); env.windows.push((surface.clone(), sink));
env.windows.push((surface.clone(), eventiter.clone()));
let decorated = wayland_window::DecoratedSurface::new( let decorated = wayland_window::DecoratedSurface::new(
&*surface, 800, 600, &*surface, 800, 600,
&env.inner.compositor, &env.inner.compositor,
@ -271,7 +270,7 @@ impl WaylandContext {
env.get_seat(), env.get_seat(),
false false
).expect("Failed to create a tmpfile buffer."); ).expect("Failed to create a tmpfile buffer.");
(surface, eventiter, decorated) (surface, decorated)
} }
pub fn prune_dead_windows(&self) { pub fn prune_dead_windows(&self) {
@ -397,13 +396,13 @@ impl wl_pointer::Handler for WaylandEnv {
surface_y: f64) surface_y: f64)
{ {
self.mouse_location = (surface_x as i32, surface_y as i32); self.mouse_location = (surface_x as i32, surface_y as i32);
for &(ref window, ref eviter) in &self.windows { for &(ref window, ref sink) in &self.windows {
if window.equals(surface) { if window.equals(surface) {
self.mouse_focus = Some(eviter.clone()); self.mouse_focus = Some((window.clone(), sink.clone()));
let (w, h) = self.mouse_location; let (w, h) = self.mouse_location;
let mut event_queue = eviter.lock().unwrap(); let mut event_queue = sink.lock().unwrap();
event_queue.push_back(Event::MouseEntered); event_queue.push_event(Event::MouseEntered, make_wid(window));
event_queue.push_back(Event::MouseMoved(w, h)); event_queue.push_event(Event::MouseMoved(w, h), make_wid(window));
break; break;
} }
} }
@ -416,10 +415,10 @@ impl wl_pointer::Handler for WaylandEnv {
surface: &wl_surface::WlSurface) surface: &wl_surface::WlSurface)
{ {
self.mouse_focus = None; self.mouse_focus = None;
for &(ref window, ref eviter) in &self.windows { for &(ref window, ref sink) in &self.windows {
if window.equals(surface) { if window.equals(surface) {
let mut event_queue = eviter.lock().unwrap(); let mut event_queue = sink.lock().unwrap();
event_queue.push_back(Event::MouseLeft); event_queue.push_event(Event::MouseLeft, make_wid(window));
break; break;
} }
} }
@ -433,10 +432,11 @@ impl wl_pointer::Handler for WaylandEnv {
surface_y: f64) surface_y: f64)
{ {
self.mouse_location = (surface_x as i32, surface_y as i32); self.mouse_location = (surface_x as i32, surface_y as i32);
if let Some(ref eviter) = self.mouse_focus { if let Some((ref window, ref sink)) = self.mouse_focus {
let (w,h) = self.mouse_location; let (w,h) = self.mouse_location;
eviter.lock().unwrap().push_back( sink.lock().unwrap().push_event(
Event::MouseMoved(w, h) Event::MouseMoved(w, h),
make_wid(window)
); );
} }
} }
@ -449,7 +449,7 @@ impl wl_pointer::Handler for WaylandEnv {
button: u32, button: u32,
state: wl_pointer::ButtonState) state: wl_pointer::ButtonState)
{ {
if let Some(ref eviter) = self.mouse_focus { if let Some((ref window, ref sink)) = self.mouse_focus {
let state = match state { let state = match state {
wl_pointer::ButtonState::Pressed => ElementState::Pressed, wl_pointer::ButtonState::Pressed => ElementState::Pressed,
wl_pointer::ButtonState::Released => ElementState::Released wl_pointer::ButtonState::Released => ElementState::Released
@ -461,8 +461,9 @@ impl wl_pointer::Handler for WaylandEnv {
// TODO figure out the translation ? // TODO figure out the translation ?
_ => return _ => return
}; };
eviter.lock().unwrap().push_back( sink.lock().unwrap().push_event(
Event::MouseInput(state, button) Event::MouseInput(state, button),
make_wid(window)
); );
} }
} }
@ -492,20 +493,22 @@ impl wl_pointer::Handler for WaylandEnv {
{ {
let axis_buffer = self.axis_buffer.take(); let axis_buffer = self.axis_buffer.take();
let axis_discrete_buffer = self.axis_discrete_buffer.take(); let axis_discrete_buffer = self.axis_discrete_buffer.take();
if let Some(ref eviter) = self.mouse_focus { if let Some((ref window, ref sink)) = self.mouse_focus {
if let Some((x, y)) = axis_discrete_buffer { if let Some((x, y)) = axis_discrete_buffer {
eviter.lock().unwrap().push_back( sink.lock().unwrap().push_event(
Event::MouseWheel( Event::MouseWheel(
MouseScrollDelta::LineDelta(x as f32, y as f32), MouseScrollDelta::LineDelta(x as f32, y as f32),
self.axis_state self.axis_state
) ),
make_wid(window)
); );
} else if let Some((x, y)) = axis_buffer { } else if let Some((x, y)) = axis_buffer {
eviter.lock().unwrap().push_back( sink.lock().unwrap().push_event(
Event::MouseWheel( Event::MouseWheel(
MouseScrollDelta::PixelDelta(x as f32, y as f32), MouseScrollDelta::PixelDelta(x as f32, y as f32),
self.axis_state self.axis_state
) ),
make_wid(window)
); );
} }
} }
@ -574,24 +577,24 @@ impl wl_keyboard::Handler for WaylandEnv {
surface: &wl_surface::WlSurface, surface: &wl_surface::WlSurface,
keys: Vec<u8>) keys: Vec<u8>)
{ {
let mut opt_eviter = None; let mut opt_sink = None;
for &(ref window, ref eviter) in &self.windows { for &(ref window, ref sink) in &self.windows {
if window.equals(surface) { if window.equals(surface) {
opt_eviter = Some(eviter.clone()); opt_sink = Some((window.clone(), sink.clone()));
break; break;
} }
} }
if let Some(ref eviter) = opt_eviter { if let Some((ref window, ref sink)) = opt_sink {
// send focused event // send focused event
let mut guard = eviter.lock().unwrap(); let mut guard = sink.lock().unwrap();
guard.push_back(Event::Focused(true)); guard.push_event(Event::Focused(true), make_wid(window));
} }
match self.kbd_handler { match self.kbd_handler {
KbdType::Mapped(ref mut h) => { KbdType::Mapped(ref mut h) => {
h.handler().target = opt_eviter; h.handler().target = opt_sink;
h.enter(evqh, proxy, serial, surface, keys); h.enter(evqh, proxy, serial, surface, keys);
}, },
KbdType::Plain(ref mut opt) => { *opt = opt_eviter; } KbdType::Plain(ref mut opt) => { *opt = opt_sink; }
} }
} }
@ -601,17 +604,17 @@ impl wl_keyboard::Handler for WaylandEnv {
serial: u32, serial: u32,
surface: &wl_surface::WlSurface) surface: &wl_surface::WlSurface)
{ {
let opt_eviter = match self.kbd_handler { let opt_sink = match self.kbd_handler {
KbdType::Mapped(ref mut h) => { KbdType::Mapped(ref mut h) => {
let eviter = h.handler().target.take(); let sink = h.handler().target.take();
h.leave(evqh, proxy, serial, surface); h.leave(evqh, proxy, serial, surface);
eviter sink
}, },
KbdType::Plain(ref mut opt) => opt.take() KbdType::Plain(ref mut opt) => opt.take()
}; };
if let Some(eviter) = opt_eviter { if let Some((ref window, ref sink)) = opt_sink {
let mut guard = eviter.lock().unwrap(); let mut guard = sink.lock().unwrap();
guard.push_back(Event::Focused(false)); guard.push_event(Event::Focused(false), make_wid(window));
} }
} }
@ -625,12 +628,12 @@ impl wl_keyboard::Handler for WaylandEnv {
{ {
match self.kbd_handler { match self.kbd_handler {
KbdType::Mapped(ref mut h) => h.key(evqh, proxy, serial, time, key, state), KbdType::Mapped(ref mut h) => h.key(evqh, proxy, serial, time, key, state),
KbdType::Plain(Some(ref eviter)) => { KbdType::Plain(Some((ref window, ref sink))) => {
let state = match state { let state = match state {
wl_keyboard::KeyState::Pressed => ElementState::Pressed, wl_keyboard::KeyState::Pressed => ElementState::Pressed,
wl_keyboard::KeyState::Released => ElementState::Released, wl_keyboard::KeyState::Released => ElementState::Released,
}; };
let mut guard = eviter.lock().unwrap(); let mut guard = sink.lock().unwrap();
// This is fallback impl if libxkbcommon was not available // This is fallback impl if libxkbcommon was not available
// This case should probably never happen, as most wayland // This case should probably never happen, as most wayland
// compositors _need_ libxkbcommon anyway... // compositors _need_ libxkbcommon anyway...
@ -638,12 +641,15 @@ impl wl_keyboard::Handler for WaylandEnv {
// In this case, we don't have the modifiers state information // In this case, we don't have the modifiers state information
// anyway, as we need libxkbcommon to interpret it (it is // anyway, as we need libxkbcommon to interpret it (it is
// supposed to be serialized by the compositor using libxkbcommon) // supposed to be serialized by the compositor using libxkbcommon)
guard.push_back(Event::KeyboardInput( guard.push_event(
Event::KeyboardInput(
state, state,
key as u8, key as u8,
None, None,
ModifiersState::default() ModifiersState::default()
)); ),
make_wid(window)
);
}, },
KbdType::Plain(None) => () KbdType::Plain(None) => ()
} }

View file

@ -0,0 +1,184 @@
use std::collections::VecDeque;
use std::sync::{Arc, Mutex};
use std::sync::atomic::AtomicBool;
use super::{DecoratedHandler, WindowId, WaylandContext};
use wayland_client::EventQueue;
use super::wayland_window::DecoratedSurface;
pub struct EventsLoopSink {
callback: Option<*mut FnMut(::Event)>,
queue: VecDeque<::Event>
}
unsafe impl Send for EventsLoopSink { }
impl EventsLoopSink {
pub fn new() -> EventsLoopSink {
EventsLoopSink {
callback: None,
queue: VecDeque::new()
}
}
pub fn push_event(&mut self, evt: ::WindowEvent, wid: WindowId) {
let evt = ::Event::WindowEvent {
event: evt,
window_id: ::WindowId(::platform::WindowId::Wayland(wid))
};
if let Some(cb) = self.callback {
unsafe { (&mut *cb)(evt) }
} else {
self.queue.push_back(evt)
}
}
// This function is only safe of the set callback is unset before exclusive
// access to the wayland EventQueue is finished.
//
// The callback also cannot be used any longer as long as it has not been
// cleared from the Sink.
unsafe fn set_callback(&mut self, cb: &mut FnMut(::Event)) {
let cb: &mut FnMut(::Event) = ::std::mem::transmute(cb);
self.callback = Some(cb as *mut _);
}
fn with_callback<F: FnOnce(&mut FnMut(::Event))>(&mut self, f: F) {
if let Some(cb) = self.callback {
f(unsafe {&mut *cb})
}
}
fn clear_callback(&mut self) {
self.callback = None
}
fn drain_queue<F: FnMut(::Event)>(&mut self, cb: &mut F) {
for evt in self.queue.drain(..) {
cb(evt)
}
}
}
pub struct EventsLoop {
ctxt: Arc<WaylandContext>,
evq: Arc<Mutex<EventQueue>>,
decorated_ids: Mutex<Vec<(usize, WindowId)>>,
sink: Arc<Mutex<EventsLoopSink>>,
interrupted: AtomicBool,
}
impl EventsLoop {
pub fn new(ctxt: Arc<WaylandContext>) -> EventsLoop {
let evq = ctxt.display.create_event_queue();
EventsLoop {
ctxt: ctxt,
evq: Arc::new(Mutex::new(evq)),
decorated_ids: Mutex::new(Vec::new()),
sink: Arc::new(Mutex::new(EventsLoopSink::new())),
interrupted: AtomicBool::new(false)
}
}
pub fn get_sink(&self) -> Arc<Mutex<EventsLoopSink>> {
self.sink.clone()
}
pub fn get_event_queue(&self) -> Arc<Mutex<EventQueue>> {
self.evq.clone()
}
pub fn register_window(&self, decorated_id: usize, wid: WindowId) {
self.decorated_ids.lock().unwrap().push((decorated_id, wid));
}
fn process_resize(evq: &mut EventQueue, ids: &[(usize, WindowId)], callback: &mut FnMut(::Event))
{
let mut state = evq.state();
for &(decorated_id, window_id) in ids {
let decorated = state.get_mut_handler::<DecoratedSurface<DecoratedHandler>>(decorated_id);
if let Some((w, h)) = decorated.handler().as_mut().and_then(|h| h.take_newsize()) {
decorated.resize(w as i32, h as i32);
callback(
::Event::WindowEvent {
window_id: ::WindowId(::platform::WindowId::Wayland(window_id)),
event: ::WindowEvent::Resized(w,h)
}
);
}
}
}
pub fn interrupt(&self) {
self.interrupted.store(true, ::std::sync::atomic::Ordering::Relaxed);
}
pub fn poll_events<F>(&self, mut callback: F)
where F: FnMut(::Event)
{
// send pending requests to the server...
self.ctxt.flush();
// first of all, get exclusive access to this event queue
let mut evq_guard = self.evq.lock().unwrap();
// dispatch stored events:
self.sink.lock().unwrap().drain_queue(&mut callback);
// read some events from the socket if some are waiting & queue is empty
if let Some(guard) = evq_guard.prepare_read() {
guard.read_events().expect("Wayland connection unexpectedly lost");
}
// set the callback into the sink
unsafe { self.sink.lock().unwrap().set_callback(&mut callback) };
// then do the actual dispatching
self.ctxt.dispatch_pending();
evq_guard.dispatch_pending().expect("Wayland connection unexpectedly lost");
let mut sink_guard = self.sink.lock().unwrap();
// events where probably dispatched, process resize
let ids_guard = self.decorated_ids.lock().unwrap();
sink_guard.with_callback(
|cb| Self::process_resize(&mut evq_guard, &ids_guard, cb)
);
sink_guard.clear_callback();
// we must keep callback alive up to this point!
drop(callback);
}
pub fn run_forever<F>(&self, mut callback: F)
where F: FnMut(::Event)
{
// send pending requests to the server...
self.ctxt.flush();
// first of all, get exclusive access to this event queue
let mut evq_guard = self.evq.lock().unwrap();
// dispatch stored events:
self.sink.lock().unwrap().drain_queue(&mut callback);
// set the callback into the sink
unsafe { self.sink.lock().unwrap().set_callback(&mut callback) };
while !self.interrupted.load(::std::sync::atomic::Ordering::Relaxed) {
self.ctxt.dispatch();
evq_guard.dispatch_pending().expect("Wayland connection unexpectedly lost");
let ids_guard = self.decorated_ids.lock().unwrap();
self.sink.lock().unwrap().with_callback(
|cb| Self::process_resize(&mut evq_guard, &ids_guard, cb)
);
self.ctxt.flush();
}
self.sink.lock().unwrap().clear_callback();
// we must keep callback alive up to this point!
drop(callback)
}
}

View file

@ -1,16 +1,15 @@
use std::collections::VecDeque;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use {VirtualKeyCode, ElementState, WindowEvent as Event}; use {VirtualKeyCode, ElementState, WindowEvent as Event};
use events::ModifiersState; use events::ModifiersState;
use super::wayland_kbd; use super::{wayland_kbd, make_wid, EventsLoopSink};
use wayland_client::EventQueueHandle; use wayland_client::EventQueueHandle;
use wayland_client::protocol::wl_keyboard; use wayland_client::protocol::{wl_keyboard, wl_surface};
pub struct KbdHandler { pub struct KbdHandler {
pub target: Option<Arc<Mutex<VecDeque<Event>>>> pub target: Option<(Arc<wl_surface::WlSurface>,Arc<Mutex<EventsLoopSink>>)>
} }
impl KbdHandler { impl KbdHandler {
@ -31,14 +30,14 @@ impl wayland_kbd::Handler for KbdHandler {
state: wl_keyboard::KeyState, state: wl_keyboard::KeyState,
utf8: Option<String>) utf8: Option<String>)
{ {
if let Some(ref eviter) = self.target { if let Some((ref window, ref sink)) = self.target {
let state = match state { let state = match state {
wl_keyboard::KeyState::Pressed => ElementState::Pressed, wl_keyboard::KeyState::Pressed => ElementState::Pressed,
wl_keyboard::KeyState::Released => ElementState::Released, wl_keyboard::KeyState::Released => ElementState::Released,
}; };
let vkcode = key_to_vkey(rawkey, keysym); let vkcode = key_to_vkey(rawkey, keysym);
let mut guard = eviter.lock().unwrap(); let mut guard = sink.lock().unwrap();
guard.push_back( guard.push_event(
Event::KeyboardInput( Event::KeyboardInput(
state, state,
rawkey as u8, rawkey as u8,
@ -49,13 +48,14 @@ impl wayland_kbd::Handler for KbdHandler {
alt: mods.alt, alt: mods.alt,
logo: mods.logo logo: mods.logo
} }
) ),
make_wid(window)
); );
// send char event only on key press, not release // send char event only on key press, not release
if let ElementState::Released = state { return } if let ElementState::Released = state { return }
if let Some(txt) = utf8 { if let Some(txt) = utf8 {
for chr in txt.chars() { for chr in txt.chars() {
guard.push_back(Event::ReceivedCharacter(chr)); guard.push_event(Event::ReceivedCharacter(chr), make_wid(window));
} }
} }
} }

View file

@ -1,122 +1,17 @@
#![cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))] #![cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))]
use self::window::Window; pub use self::window::{Window as Window2, WindowId};
pub use self::event_loop::EventsLoop;
pub use self::context::{WaylandContext, MonitorId, get_available_monitors, pub use self::context::{WaylandContext, MonitorId, get_available_monitors,
get_primary_monitor}; get_primary_monitor};
use self::window::{make_wid, DecoratedHandler};
use self::event_loop::EventsLoopSink;
extern crate wayland_kbd; extern crate wayland_kbd;
extern crate wayland_window; extern crate wayland_window;
use CreationError;
use std::sync::Arc;
mod context; mod context;
mod event_loop;
mod keyboard; mod keyboard;
mod window; mod window;
// API TRANSITION
//
// We don't use the gen_api_transistion!() macro but rather do the expansion manually:
//
// As this module is nested into platform/linux, its code is not _exactly_ the same as
// the one generated by the macro.
pub struct EventsLoop {
windows: ::std::sync::Mutex<Vec<::std::sync::Arc<Window>>>,
interrupted: ::std::sync::atomic::AtomicBool,
}
impl EventsLoop {
pub fn new() -> EventsLoop {
EventsLoop {
windows: ::std::sync::Mutex::new(vec![]),
interrupted: ::std::sync::atomic::AtomicBool::new(false),
}
}
pub fn interrupt(&self) {
self.interrupted.store(true, ::std::sync::atomic::Ordering::Relaxed);
}
pub fn poll_events<F>(&self, mut callback: F)
where F: FnMut(::Event)
{
let windows = self.windows.lock().unwrap();
for window in windows.iter() {
for event in window.poll_events() {
callback(::Event::WindowEvent {
window_id: ::WindowId(::platform::WindowId::Wayland(WindowId(&**window as *const Window as usize))),
event: event,
})
}
}
}
pub fn run_forever<F>(&self, mut callback: F)
where F: FnMut(::Event)
{
self.interrupted.store(false, ::std::sync::atomic::Ordering::Relaxed);
// Yeah that's a very bad implementation.
loop {
self.poll_events(|e| callback(e));
::std::thread::sleep(::std::time::Duration::from_millis(5));
if self.interrupted.load(::std::sync::atomic::Ordering::Relaxed) {
break;
}
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct WindowId(usize);
pub struct Window2 {
pub window: ::std::sync::Arc<Window>,
events_loop: ::std::sync::Weak<::platform::EventsLoop>,
}
impl ::std::ops::Deref for Window2 {
type Target = Window;
#[inline]
fn deref(&self) -> &Window {
&*self.window
}
}
impl Window2 {
pub fn new(events_loop: ::std::sync::Arc<::platform::EventsLoop>, ctxt: Arc<WaylandContext>,
window: &::WindowAttributes)
-> Result<Window2, CreationError>
{
let win = ::std::sync::Arc::new(try!(Window::new(ctxt, window)));
if let ::platform::EventsLoop::Wayland(ref ev) = *events_loop {
ev.windows.lock().unwrap().push(win.clone());
} else {
// It should not be possible to create an eventloop not matching the backend
// in use
unreachable!()
}
Ok(Window2 {
window: win,
events_loop: ::std::sync::Arc::downgrade(&events_loop),
})
}
#[inline]
pub fn id(&self) -> WindowId {
WindowId(&*self.window as *const Window as usize)
}
}
impl Drop for Window2 {
fn drop(&mut self) {
if let Some(ev) = self.events_loop.upgrade() {
if let ::platform::EventsLoop::Wayland(ref ev) = *ev {
let mut windows = ev.windows.lock().unwrap();
windows.retain(|w| &**w as *const Window != &*self.window as *const _);
}
}
}
}

View file

@ -1,51 +1,45 @@
use std::collections::VecDeque;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use wayland_client::{EventQueue, EventQueueHandle, Init}; use wayland_client::{EventQueue, EventQueueHandle, Init, Proxy};
use wayland_client::protocol::{wl_display,wl_surface,wl_shell_surface}; use wayland_client::protocol::{wl_display,wl_surface,wl_shell_surface};
use {CreationError, MouseCursor, CursorState, WindowEvent as Event, WindowAttributes}; use {CreationError, MouseCursor, CursorState, WindowAttributes};
use platform::MonitorId as PlatformMonitorId; use platform::MonitorId as PlatformMonitorId;
use super::WaylandContext; use super::{WaylandContext, EventsLoop};
use super::wayland_window; use super::wayland_window;
use super::wayland_window::DecoratedSurface; use super::wayland_window::DecoratedSurface;
pub struct Window { pub struct Window {
ctxt: Arc<WaylandContext>, ctxt: Arc<WaylandContext>,
evq: Mutex<EventQueue>, evq: Arc<Mutex<EventQueue>>,
eviter: Arc<Mutex<VecDeque<Event>>>,
surface: Arc<wl_surface::WlSurface>, surface: Arc<wl_surface::WlSurface>,
size: Mutex<(u32, u32)>, size: Mutex<(u32, u32)>,
handler_id: usize,
decorated_id: usize decorated_id: usize
} }
pub struct PollEventsIterator<'a> { #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
window: &'a Window, pub struct WindowId(usize);
}
impl<'a> Iterator for PollEventsIterator<'a> { #[inline]
type Item = Event; pub fn make_wid(s: &wl_surface::WlSurface) -> WindowId {
WindowId(s.ptr() as usize)
fn next(&mut self) -> Option<Event> {
self.window.next_event(false)
}
} }
impl Window { impl Window {
pub fn new(ctxt: Arc<WaylandContext>, attributes: &WindowAttributes) -> Result<Window, CreationError> pub fn new(evlp: &EventsLoop, ctxt: Arc<WaylandContext>, attributes: &WindowAttributes) -> Result<Window, CreationError>
{ {
let (width, height) = attributes.dimensions.unwrap_or((800,600)); let (width, height) = attributes.dimensions.unwrap_or((800,600));
let mut evq = ctxt.display.create_event_queue(); let (surface, decorated) = ctxt.create_window::<DecoratedHandler>(evlp.get_sink());
let (surface, eviter, decorated) = ctxt.create_window::<DecoratedHandler>();
// init DecoratedSurface // init DecoratedSurface
let decorated_id = evq.add_handler_with_init(decorated); let evq = evlp.get_event_queue();
let decorated_id = {
let mut evq_guard = evq.lock().unwrap();
let decorated_id = evq_guard.add_handler_with_init(decorated);
{ {
let mut state = evq.state(); let mut state = evq_guard.state();
let decorated = state.get_mut_handler::<DecoratedSurface<DecoratedHandler>>(decorated_id); let decorated = state.get_mut_handler::<DecoratedSurface<DecoratedHandler>>(decorated_id);
*(decorated.handler()) = Some(DecoratedHandler::new()); *(decorated.handler()) = Some(DecoratedHandler::new());
@ -63,79 +57,24 @@ impl Window {
// Finally, set the decorations size // Finally, set the decorations size
decorated.resize(width as i32, height as i32); decorated.resize(width as i32, height as i32);
} }
decorated_id
// init general handler };
let handler = WindowHandler::new(); let me = Window {
let handler_id = evq.add_handler_with_init(handler);
Ok(Window {
ctxt: ctxt, ctxt: ctxt,
evq: Mutex::new(evq), evq: evq,
eviter: eviter,
surface: surface, surface: surface,
size: Mutex::new((width, height)), size: Mutex::new((width, height)),
handler_id: handler_id,
decorated_id: decorated_id decorated_id: decorated_id
})
}
fn process_resize(&self) {
let mut evq_guard = self.evq.lock().unwrap();
let mut state = evq_guard.state();
let decorated = state.get_mut_handler::<DecoratedSurface<DecoratedHandler>>(self.decorated_id);
if let Some((w, h)) = decorated.handler().as_mut().and_then(|h| h.take_newsize()) {
decorated.resize(w as i32, h as i32);
*self.size.lock().unwrap() = (w, h);
self.eviter.lock().unwrap().push_back(Event::Resized(w,h));
}
}
fn next_event(&self, block: bool) -> Option<Event> {
let mut evt = {
let mut guard = self.eviter.lock().unwrap();
guard.pop_front()
};
if evt.is_some() { return evt }
// There is no event in the queue, we need to fetch more
// flush the display
self.ctxt.flush();
// read some events if some are waiting & queue is empty
if let Some(guard) = self.evq.lock().unwrap().prepare_read() {
guard.read_events().expect("Wayland connection unexpectedly lost");
}
// try a pending dispatch
{
self.ctxt.dispatch_pending();
self.evq.lock().unwrap().dispatch_pending()
.expect("Wayland connection unexpectedly lost");
// some events were dispatched, need to process a potential resising
self.process_resize();
}
evt = {
let mut guard = self.eviter.lock().unwrap();
guard.pop_front()
}; };
while block && evt.is_none() { evlp.register_window(me.decorated_id, me.id());
// no event waiting, need to repopulate!
{ Ok(me)
self.ctxt.flush();
self.ctxt.dispatch();
self.evq.lock().unwrap().dispatch_pending()
.expect("Wayland connection unexpectedly lost");
// some events were dispatched, need to process a potential resising
self.process_resize();
} }
// try again
let mut guard = self.eviter.lock().unwrap(); #[inline]
evt = guard.pop_front(); pub fn id(&self) -> WindowId {
} make_wid(&self.surface)
evt
} }
pub fn set_title(&self, title: &str) { pub fn set_title(&self, title: &str) {
@ -186,13 +125,6 @@ impl Window {
decorated.resize(x as i32, y as i32); decorated.resize(x as i32, y as i32);
} }
#[inline]
pub fn poll_events(&self) -> PollEventsIterator {
PollEventsIterator {
window: self
}
}
#[inline] #[inline]
pub fn set_cursor(&self, _cursor: MouseCursor) { pub fn set_cursor(&self, _cursor: MouseCursor) {
// TODO // TODO
@ -237,13 +169,14 @@ impl Drop for Window {
} }
} }
struct DecoratedHandler { pub struct DecoratedHandler {
newsize: Option<(u32, u32)> newsize: Option<(u32, u32)>
} }
impl DecoratedHandler { impl DecoratedHandler {
fn new() -> DecoratedHandler { DecoratedHandler { newsize: None }} fn new() -> DecoratedHandler { DecoratedHandler { newsize: None }}
fn take_newsize(&mut self) -> Option<(u32, u32)> {
pub fn take_newsize(&mut self) -> Option<(u32, u32)> {
self.newsize.take() self.newsize.take()
} }
} }
@ -258,21 +191,3 @@ impl wayland_window::Handler for DecoratedHandler {
self.newsize = Some((max(width,1) as u32, max(height,1) as u32)); self.newsize = Some((max(width,1) as u32, max(height,1) as u32));
} }
} }
struct WindowHandler {
my_id: usize,
}
impl WindowHandler {
fn new() -> WindowHandler {
WindowHandler {
my_id: 0,
}
}
}
impl Init for WindowHandler {
fn init(&mut self, _evqh: &mut EventQueueHandle, index: usize) {
self.my_id = index;
}
}