Implement changes to RedrawRequested event (#1062)

* Implement changes to `RedrawRequested` event

Implements the changes described in #1041 for the X11 platform and for
platform-independent public-facing code.

* Fix `request_redraw` example

* Fix examples in lib docs

* Only issue `RedrawRequested` on final `Expose` event
This commit is contained in:
Murarth 2019-07-30 23:31:12 -07:00 committed by Osspial
parent c10c820311
commit 0c151f9fb3
7 changed files with 67 additions and 37 deletions

View file

@ -100,6 +100,11 @@
- On iOS, fix DPI sent out by views on creation was `0.0` - now it gives a reasonable number. - On iOS, fix DPI sent out by views on creation was `0.0` - now it gives a reasonable number.
- On iOS, RedrawRequested now works for gl/metal backed views. - On iOS, RedrawRequested now works for gl/metal backed views.
- On iOS, RedrawRequested is generally ordered after EventsCleared. - On iOS, RedrawRequested is generally ordered after EventsCleared.
- Changes to the `RedrawRequested` event (#1041):
- `RedrawRequested` has been moved from `WindowEvent` to `Event`.
- `EventsCleared` has been renamed to `MainEventsCleared`.
- `RedrawRequested` is now issued only after `MainEventsCleared`.
- `RedrawEventsCleared` is issued after each set of `RedrawRequested` events.
# 0.20.0 Alpha 2 (2019-07-09) # 0.20.0 Alpha 2 (2019-07-09)

View file

@ -20,14 +20,11 @@ fn main() {
event: WindowEvent::CloseRequested, event: WindowEvent::CloseRequested,
.. ..
} => *control_flow = ControlFlow::Exit, } => *control_flow = ControlFlow::Exit,
Event::EventsCleared => { Event::MainEventsCleared => {
window.request_redraw(); window.request_redraw();
*control_flow = ControlFlow::WaitUntil(Instant::now() + Duration::new(1, 0)) *control_flow = ControlFlow::WaitUntil(Instant::now() + Duration::new(1, 0))
} }
Event::WindowEvent { Event::RedrawRequested(_) => {
event: WindowEvent::RedrawRequested,
..
} => {
println!("{:?}", event); println!("{:?}", event);
} }
_ => (), _ => (),

View file

@ -30,9 +30,22 @@ pub enum Event<T> {
UserEvent(T), UserEvent(T),
/// Emitted when new events arrive from the OS to be processed. /// Emitted when new events arrive from the OS to be processed.
NewEvents(StartCause), NewEvents(StartCause),
/// Emitted when all of the event loop's events have been processed and control flow is about /// Emitted when all events (except for `RedrawRequested`) have been reported.
/// to be taken away from the program. ///
EventsCleared, /// This event is followed by zero or more instances of `RedrawRequested`
/// and, finally, `RedrawEventsCleared`.
MainEventsCleared,
/// The OS or application has requested that a window be redrawn.
///
/// Emitted only after `MainEventsCleared`.
RedrawRequested(WindowId),
/// Emitted after any `RedrawRequested` events.
///
/// If there are no `RedrawRequested` events, it is reported immediately after
/// `MainEventsCleared`.
RedrawEventsCleared,
/// Emitted when the event loop is being shut down. This is irreversable - if this event is /// Emitted when the event loop is being shut down. This is irreversable - if this event is
/// emitted, it is guaranteed to be the last event emitted. /// emitted, it is guaranteed to be the last event emitted.
@ -53,7 +66,9 @@ impl<T> Event<T> {
WindowEvent { window_id, event } => Ok(WindowEvent { window_id, event }), WindowEvent { window_id, event } => Ok(WindowEvent { window_id, event }),
DeviceEvent { device_id, event } => Ok(DeviceEvent { device_id, event }), DeviceEvent { device_id, event } => Ok(DeviceEvent { device_id, event }),
NewEvents(cause) => Ok(NewEvents(cause)), NewEvents(cause) => Ok(NewEvents(cause)),
EventsCleared => Ok(EventsCleared), MainEventsCleared => Ok(MainEventsCleared),
RedrawRequested(wid) => Ok(RedrawRequested(wid)),
RedrawEventsCleared => Ok(RedrawEventsCleared),
LoopDestroyed => Ok(LoopDestroyed), LoopDestroyed => Ok(LoopDestroyed),
Suspended => Ok(Suspended), Suspended => Ok(Suspended),
Resumed => Ok(Resumed), Resumed => Ok(Resumed),
@ -194,9 +209,6 @@ pub enum WindowEvent {
value: f64, value: f64,
}, },
/// The OS or application has requested that the window be redrawn.
RedrawRequested,
/// Touch event has been received /// Touch event has been received
Touch(Touch), Touch(Touch),

View file

@ -48,19 +48,16 @@
//! //!
//! event_loop.run(move |event, _, control_flow| { //! event_loop.run(move |event, _, control_flow| {
//! match event { //! match event {
//! Event::EventsCleared => { //! Event::MainEventsCleared => {
//! // Application update code. //! // Application update code.
//! //!
//! // Queue a RedrawRequested event. //! // Queue a RedrawRequested event.
//! window.request_redraw(); //! window.request_redraw();
//! }, //! },
//! Event::WindowEvent { //! Event::RedrawRequested(_) => {
//! event: WindowEvent::RedrawRequested,
//! ..
//! } => {
//! // Redraw the application. //! // Redraw the application.
//! // //! //
//! // It's preferrable to render in this event rather than in EventsCleared, since //! // It's preferrable to render in this event rather than in MainEventsCleared, since
//! // rendering in here allows the program to gracefully handle redraws requested //! // rendering in here allows the program to gracefully handle redraws requested
//! // by the OS. //! // by the OS.
//! }, //! },

View file

@ -526,7 +526,7 @@ impl<T: 'static> EventLoop<T> {
// send Events cleared // send Events cleared
{ {
sticky_exit_callback( sticky_exit_callback(
crate::event::Event::EventsCleared, crate::event::Event::MainEventsCleared,
&self.window_target, &self.window_target,
&mut control_flow, &mut control_flow,
&mut callback, &mut callback,
@ -704,7 +704,8 @@ impl<T> EventLoop<T> {
); );
} }
if window.refresh { if window.refresh {
sink.send_window_event(crate::event::WindowEvent::RedrawRequested, window.wid); unimplemented!()
//sink.send_window_event(crate::event::WindowEvent::RedrawRequested, window.wid);
} }
if window.closed { if window.closed {
sink.send_window_event(crate::event::WindowEvent::CloseRequested, window.wid); sink.send_window_event(crate::event::WindowEvent::CloseRequested, window.wid);

View file

@ -534,13 +534,14 @@ impl<T: 'static> EventProcessor<T> {
ffi::Expose => { ffi::Expose => {
let xev: &ffi::XExposeEvent = xev.as_ref(); let xev: &ffi::XExposeEvent = xev.as_ref();
// Multiple Expose events may be received for subareas of a window.
// We issue `RedrawRequested` only for the last event of such a series.
if xev.count == 0 {
let window = xev.window; let window = xev.window;
let window_id = mkwid(window); let window_id = mkwid(window);
callback(Event::WindowEvent { callback(Event::RedrawRequested(window_id));
window_id, }
event: WindowEvent::RedrawRequested,
});
} }
ffi::KeyPress | ffi::KeyRelease => { ffi::KeyPress | ffi::KeyRelease => {

View file

@ -45,7 +45,7 @@ use self::{
}; };
use crate::{ use crate::{
error::OsError as RootOsError, error::OsError as RootOsError,
event::{Event, StartCause, WindowEvent}, event::{Event, StartCause},
event_loop::{ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootELW}, event_loop::{ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootELW},
platform_impl::{platform::sticky_exit_callback, PlatformSpecificWindowBuilderAttributes}, platform_impl::{platform::sticky_exit_callback, PlatformSpecificWindowBuilderAttributes},
window::WindowAttributes, window::WindowAttributes,
@ -151,6 +151,8 @@ impl<T: 'static> EventLoop<T> {
xconn.update_cached_wm_info(root); xconn.update_cached_wm_info(root);
let pending_redraws: Arc<Mutex<HashSet<WindowId>>> = Default::default();
let mut mod_keymap = ModifierKeymap::new(); let mut mod_keymap = ModifierKeymap::new();
mod_keymap.reset_from_x_connection(&xconn); mod_keymap.reset_from_x_connection(&xconn);
@ -164,7 +166,7 @@ impl<T: 'static> EventLoop<T> {
xconn, xconn,
wm_delete_window, wm_delete_window,
net_wm_ping, net_wm_ping,
pending_redraws: Default::default(), pending_redraws: pending_redraws.clone(),
}), }),
_marker: ::std::marker::PhantomData, _marker: ::std::marker::PhantomData,
}); });
@ -227,7 +229,9 @@ impl<T: 'static> EventLoop<T> {
if evt.readiness.is_readable() { if evt.readiness.is_readable() {
let mut processor = processor.borrow_mut(); let mut processor = processor.borrow_mut();
let mut pending_events = pending_events.borrow_mut(); let mut pending_events = pending_events.borrow_mut();
drain_events(&mut processor, &mut pending_events); let mut pending_redraws = pending_redraws.lock().unwrap();
drain_events(&mut processor, &mut pending_events, &mut pending_redraws);
} }
} }
}) })
@ -293,6 +297,15 @@ impl<T: 'static> EventLoop<T> {
); );
} }
} }
// send MainEventsCleared
{
sticky_exit_callback(
crate::event::Event::MainEventsCleared,
&self.target,
&mut control_flow,
&mut callback,
);
}
// Empty the redraw requests // Empty the redraw requests
{ {
// Release the lock to prevent deadlock // Release the lock to prevent deadlock
@ -300,20 +313,17 @@ impl<T: 'static> EventLoop<T> {
for wid in windows { for wid in windows {
sticky_exit_callback( sticky_exit_callback(
Event::WindowEvent { Event::RedrawRequested(crate::window::WindowId(super::WindowId::X(wid))),
window_id: crate::window::WindowId(super::WindowId::X(wid)),
event: WindowEvent::RedrawRequested,
},
&self.target, &self.target,
&mut control_flow, &mut control_flow,
&mut callback, &mut callback,
); );
} }
} }
// send Events cleared // send RedrawEventsCleared
{ {
sticky_exit_callback( sticky_exit_callback(
crate::event::Event::EventsCleared, crate::event::Event::RedrawEventsCleared,
&self.target, &self.target,
&mut control_flow, &mut control_flow,
&mut callback, &mut callback,
@ -392,8 +402,10 @@ impl<T: 'static> EventLoop<T> {
fn drain_events(&self) { fn drain_events(&self) {
let mut processor = self.event_processor.borrow_mut(); let mut processor = self.event_processor.borrow_mut();
let mut pending_events = self.pending_events.borrow_mut(); let mut pending_events = self.pending_events.borrow_mut();
let wt = get_xtarget(&self.target);
let mut pending_redraws = wt.pending_redraws.lock().unwrap();
drain_events(&mut processor, &mut pending_events); drain_events(&mut processor, &mut pending_events, &mut pending_redraws);
} }
fn events_waiting(&self) -> bool { fn events_waiting(&self) -> bool {
@ -404,9 +416,14 @@ impl<T: 'static> EventLoop<T> {
fn drain_events<T: 'static>( fn drain_events<T: 'static>(
processor: &mut EventProcessor<T>, processor: &mut EventProcessor<T>,
pending_events: &mut VecDeque<Event<T>>, pending_events: &mut VecDeque<Event<T>>,
pending_redraws: &mut HashSet<WindowId>,
) { ) {
let mut callback = |event| { let mut callback = |event| {
if let Event::RedrawRequested(crate::window::WindowId(super::WindowId::X(wid))) = event {
pending_redraws.insert(wid);
} else {
pending_events.push_back(event); pending_events.push_back(event);
}
}; };
// process all pending events // process all pending events