From 1b22e39fb27e66ceee1036b8214397f168374e3e Mon Sep 17 00:00:00 2001 From: Victor Berger Date: Thu, 31 Aug 2017 19:43:24 +0200 Subject: [PATCH] wayland: internal event buffer & wait for xdg configure (#255) --- Cargo.toml | 2 +- src/platform/linux/wayland/event_loop.rs | 40 +++++++++++++++++++----- src/platform/linux/wayland/window.rs | 12 ++++--- 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d0d597a7..c7d6fe1c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/src/platform/linux/wayland/event_loop.rs b/src/platform/linux/wayland/event_loop.rs index 031d992f..8a7a8387 100644 --- a/src/platform/linux/wayland/event_loop.rs +++ b/src/platform/linux/wayland/event_loop.rs @@ -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>>) { + 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)>>, // our sink, receiver of callbacks, shared with some handlers sink: Arc>, + // a buffer in which events that were dispatched internally are stored + // until the user next dispatches events + buffer: Arc>>, // trigger cleanup of the dead surfaces cleanup_needed: Arc, // 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) -> 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) { + 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(&mut self, callback: F) + fn empty_buffer(&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(&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 diff --git a/src/platform/linux/wayland/window.rs b/src/platform/linux/wayland/window.rs index 44935f14..489bee1e 100644 --- a/src/platform/linux/wayland/window.rs +++ b/src/platform/linux/wayland/window.rs @@ -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) {