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-protocols = { version = "0.9.9", features = ["unstable_protocols"] }
wayland-kbd = "0.9.1"
wayland-window = "0.7.0"
wayland-window = "0.8.0"
tempfile = "2.1"
x11-dl = "2.8"

View file

@ -1,6 +1,7 @@
use {WindowEvent as Event, ElementState, MouseButton, MouseScrollDelta, TouchPhase, ModifiersState,
KeyboardInput, EventsLoopClosed, ControlFlow};
use std::collections::VecDeque;
use std::sync::{Arc, Mutex, Weak};
use std::sync::atomic::{self, AtomicBool};
@ -31,10 +32,13 @@ pub struct EventsLoopSink {
unsafe impl Send for EventsLoopSink { }
impl EventsLoopSink {
pub fn new() -> EventsLoopSink {
EventsLoopSink {
callback: Box::new(|_| {}),
}
pub fn new() -> (EventsLoopSink, Arc<Mutex<VecDeque<::Event>>>) {
let buffer = Arc::new(Mutex::new(VecDeque::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) {
@ -70,6 +74,9 @@ pub struct EventsLoop {
decorated_ids: Mutex<Vec<(usize, Arc<wl_surface::WlSurface>)>>,
// our sink, receiver of callbacks, shared with some handlers
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
cleanup_needed: Arc<AtomicBool>,
// Whether or not there is a pending `Awakened` event to be emitted.
@ -109,13 +116,15 @@ impl EventsLoopProxy {
impl EventsLoop {
pub fn new(ctxt: Arc<WaylandContext>) -> EventsLoop {
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()));
EventsLoop {
ctxt: ctxt,
evq: Arc::new(Mutex::new(evq)),
decorated_ids: Mutex::new(Vec::new()),
sink: sink,
buffer: buffer,
pending_wakeup: Arc::new(AtomicBool::new(false)),
cleanup_needed: Arc::new(AtomicBool::new(false)),
hid: hid
@ -135,6 +144,10 @@ impl EventsLoop {
}
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()));
let mut guard = self.evq.lock().unwrap();
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)
{
// send pending requests to the server...
@ -189,6 +209,9 @@ impl EventsLoop {
// first of all, get exclusive access to this event queue
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
if let Some(guard) = evq_guard.prepare_read() {
guard.read_events().expect("Wayland connection unexpectedly lost");
@ -235,10 +258,13 @@ impl EventsLoop {
// Check for control flow by wrapping the callback.
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);
};
// dispatch pre-buffered events
self.empty_buffer(&mut callback);
// set the callback into the sink
// 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

View file

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