wayland: internal event buffer & wait for xdg configure (#255)

This commit is contained in:
Victor Berger 2017-08-31 19:43:24 +02:00 committed by tomaka
parent 7dc6fcdedc
commit 1b22e39fb2
3 changed files with 42 additions and 12 deletions

View file

@ -39,6 +39,6 @@ dwmapi-sys = "0.1"
wayland-client = { version = "0.9.9", features = ["dlopen"] } wayland-client = { version = "0.9.9", features = ["dlopen"] }
wayland-protocols = { version = "0.9.9", features = ["unstable_protocols"] } wayland-protocols = { version = "0.9.9", features = ["unstable_protocols"] }
wayland-kbd = "0.9.1" wayland-kbd = "0.9.1"
wayland-window = "0.7.0" wayland-window = "0.8.0"
tempfile = "2.1" tempfile = "2.1"
x11-dl = "2.8" x11-dl = "2.8"

View file

@ -1,6 +1,7 @@
use {WindowEvent as Event, ElementState, MouseButton, MouseScrollDelta, TouchPhase, ModifiersState, use {WindowEvent as Event, ElementState, MouseButton, MouseScrollDelta, TouchPhase, ModifiersState,
KeyboardInput, EventsLoopClosed, ControlFlow}; KeyboardInput, EventsLoopClosed, ControlFlow};
use std::collections::VecDeque;
use std::sync::{Arc, Mutex, Weak}; use std::sync::{Arc, Mutex, Weak};
use std::sync::atomic::{self, AtomicBool}; use std::sync::atomic::{self, AtomicBool};
@ -31,10 +32,13 @@ pub struct EventsLoopSink {
unsafe impl Send for EventsLoopSink { } unsafe impl Send for EventsLoopSink { }
impl EventsLoopSink { impl EventsLoopSink {
pub fn new() -> EventsLoopSink { pub fn new() -> (EventsLoopSink, Arc<Mutex<VecDeque<::Event>>>) {
EventsLoopSink { let buffer = Arc::new(Mutex::new(VecDeque::new()));
callback: Box::new(|_| {}), let buffer_clone = buffer.clone();
} let sink = EventsLoopSink {
callback: Box::new(move |evt| { println!("TEMP: {:?}", evt); buffer.lock().unwrap().push_back(evt)}),
};
(sink, buffer_clone)
} }
pub fn send_event(&mut self, evt: ::WindowEvent, wid: WindowId) { pub fn send_event(&mut self, evt: ::WindowEvent, wid: WindowId) {
@ -70,6 +74,9 @@ pub struct EventsLoop {
decorated_ids: Mutex<Vec<(usize, Arc<wl_surface::WlSurface>)>>, decorated_ids: Mutex<Vec<(usize, Arc<wl_surface::WlSurface>)>>,
// our sink, receiver of callbacks, shared with some handlers // our sink, receiver of callbacks, shared with some handlers
sink: Arc<Mutex<EventsLoopSink>>, sink: Arc<Mutex<EventsLoopSink>>,
// a buffer in which events that were dispatched internally are stored
// until the user next dispatches events
buffer: Arc<Mutex<VecDeque<::Event>>>,
// trigger cleanup of the dead surfaces // trigger cleanup of the dead surfaces
cleanup_needed: Arc<AtomicBool>, cleanup_needed: Arc<AtomicBool>,
// Whether or not there is a pending `Awakened` event to be emitted. // Whether or not there is a pending `Awakened` event to be emitted.
@ -109,13 +116,15 @@ impl EventsLoopProxy {
impl EventsLoop { impl EventsLoop {
pub fn new(ctxt: Arc<WaylandContext>) -> EventsLoop { pub fn new(ctxt: Arc<WaylandContext>) -> EventsLoop {
let mut evq = ctxt.display.create_event_queue(); let mut evq = ctxt.display.create_event_queue();
let sink = Arc::new(Mutex::new(EventsLoopSink::new())); let (sink, buffer) = EventsLoopSink::new();
let sink = Arc::new(Mutex::new(sink));
let hid = evq.add_handler_with_init(InputHandler::new(&ctxt, sink.clone())); let hid = evq.add_handler_with_init(InputHandler::new(&ctxt, sink.clone()));
EventsLoop { EventsLoop {
ctxt: ctxt, ctxt: ctxt,
evq: Arc::new(Mutex::new(evq)), evq: Arc::new(Mutex::new(evq)),
decorated_ids: Mutex::new(Vec::new()), decorated_ids: Mutex::new(Vec::new()),
sink: sink, sink: sink,
buffer: buffer,
pending_wakeup: Arc::new(AtomicBool::new(false)), pending_wakeup: Arc::new(AtomicBool::new(false)),
cleanup_needed: Arc::new(AtomicBool::new(false)), cleanup_needed: Arc::new(AtomicBool::new(false)),
hid: hid hid: hid
@ -135,6 +144,10 @@ impl EventsLoop {
} }
pub fn register_window(&self, decorated_id: usize, surface: Arc<wl_surface::WlSurface>) { pub fn register_window(&self, decorated_id: usize, surface: Arc<wl_surface::WlSurface>) {
self.buffer.lock().unwrap().push_back(::Event::WindowEvent {
window_id: ::WindowId(::platform::WindowId::Wayland(make_wid(&surface))),
event: ::WindowEvent::Refresh
});
self.decorated_ids.lock().unwrap().push((decorated_id, surface.clone())); self.decorated_ids.lock().unwrap().push((decorated_id, surface.clone()));
let mut guard = self.evq.lock().unwrap(); let mut guard = self.evq.lock().unwrap();
let mut state = guard.state(); let mut state = guard.state();
@ -180,7 +193,14 @@ impl EventsLoop {
} }
} }
pub fn poll_events<F>(&mut self, callback: F) fn empty_buffer<F>(&self, callback: &mut F) where F: FnMut(::Event) {
let mut guard = self.buffer.lock().unwrap();
for evt in guard.drain(..) {
callback(evt)
}
}
pub fn poll_events<F>(&mut self, mut callback: F)
where F: FnMut(::Event) where F: FnMut(::Event)
{ {
// send pending requests to the server... // send pending requests to the server...
@ -189,6 +209,9 @@ impl EventsLoop {
// first of all, get exclusive access to this event queue // first of all, get exclusive access to this event queue
let mut evq_guard = self.evq.lock().unwrap(); let mut evq_guard = self.evq.lock().unwrap();
// dispatch pre-buffered events
self.empty_buffer(&mut callback);
// read some events from the socket if some are waiting & queue is empty // read some events from the socket if some are waiting & queue is empty
if let Some(guard) = evq_guard.prepare_read() { if let Some(guard) = evq_guard.prepare_read() {
guard.read_events().expect("Wayland connection unexpectedly lost"); guard.read_events().expect("Wayland connection unexpectedly lost");
@ -235,10 +258,13 @@ impl EventsLoop {
// Check for control flow by wrapping the callback. // Check for control flow by wrapping the callback.
let control_flow = ::std::cell::Cell::new(ControlFlow::Continue); let control_flow = ::std::cell::Cell::new(ControlFlow::Continue);
let callback = |event| if let ControlFlow::Break = callback(event) { let mut callback = |event| if let ControlFlow::Break = callback(event) {
control_flow.set(ControlFlow::Break); control_flow.set(ControlFlow::Break);
}; };
// dispatch pre-buffered events
self.empty_buffer(&mut callback);
// set the callback into the sink // set the callback into the sink
// we extend the lifetime of the closure to 'static to be able to put it in // we extend the lifetime of the closure to 'static to be able to put it in
// the sink, but we'll explicitly drop it at the end of this function, so it's fine // the sink, but we'll explicitly drop it at the end of this function, so it's fine

View file

@ -66,6 +66,9 @@ 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);
} }
evq_guard.sync_roundtrip().unwrap();
decorated_id decorated_id
}; };
let me = Window { let me = Window {
@ -204,11 +207,12 @@ impl DecoratedHandler {
impl wayland_window::Handler for DecoratedHandler { impl wayland_window::Handler for DecoratedHandler {
fn configure(&mut self, fn configure(&mut self,
_: &mut EventQueueHandle, _: &mut EventQueueHandle,
_: wayland_window::Configure, _cfg: wayland_window::Configure,
width: i32, height: i32) newsize: Option<(i32, i32)>)
{ {
use std::cmp::max; if let Some((w, h)) = newsize {
self.newsize = Some((max(width,1) as u32, max(height,1) as u32)); self.newsize = Some((w as u32, h as u32));
}
} }
fn close(&mut self, _: &mut EventQueueHandle) { fn close(&mut self, _: &mut EventQueueHandle) {