diff --git a/CHANGELOG.md b/CHANGELOG.md index b1bd2d66..dd0db09b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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, RedrawRequested now works for gl/metal backed views. - 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) diff --git a/examples/request_redraw.rs b/examples/request_redraw.rs index b55bd970..a84cffe9 100644 --- a/examples/request_redraw.rs +++ b/examples/request_redraw.rs @@ -20,14 +20,11 @@ fn main() { event: WindowEvent::CloseRequested, .. } => *control_flow = ControlFlow::Exit, - Event::EventsCleared => { + Event::MainEventsCleared => { window.request_redraw(); *control_flow = ControlFlow::WaitUntil(Instant::now() + Duration::new(1, 0)) } - Event::WindowEvent { - event: WindowEvent::RedrawRequested, - .. - } => { + Event::RedrawRequested(_) => { println!("{:?}", event); } _ => (), diff --git a/src/event.rs b/src/event.rs index 318a3578..9e3a838d 100644 --- a/src/event.rs +++ b/src/event.rs @@ -30,9 +30,22 @@ pub enum Event { UserEvent(T), /// Emitted when new events arrive from the OS to be processed. NewEvents(StartCause), - /// Emitted when all of the event loop's events have been processed and control flow is about - /// to be taken away from the program. - EventsCleared, + /// Emitted when all events (except for `RedrawRequested`) have been reported. + /// + /// 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, it is guaranteed to be the last event emitted. @@ -53,7 +66,9 @@ impl Event { WindowEvent { window_id, event } => Ok(WindowEvent { window_id, event }), DeviceEvent { device_id, event } => Ok(DeviceEvent { device_id, event }), NewEvents(cause) => Ok(NewEvents(cause)), - EventsCleared => Ok(EventsCleared), + MainEventsCleared => Ok(MainEventsCleared), + RedrawRequested(wid) => Ok(RedrawRequested(wid)), + RedrawEventsCleared => Ok(RedrawEventsCleared), LoopDestroyed => Ok(LoopDestroyed), Suspended => Ok(Suspended), Resumed => Ok(Resumed), @@ -194,9 +209,6 @@ pub enum WindowEvent { value: f64, }, - /// The OS or application has requested that the window be redrawn. - RedrawRequested, - /// Touch event has been received Touch(Touch), diff --git a/src/lib.rs b/src/lib.rs index 92b35b41..9d0340ee 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -48,19 +48,16 @@ //! //! event_loop.run(move |event, _, control_flow| { //! match event { -//! Event::EventsCleared => { +//! Event::MainEventsCleared => { //! // Application update code. //! //! // Queue a RedrawRequested event. //! window.request_redraw(); //! }, -//! Event::WindowEvent { -//! event: WindowEvent::RedrawRequested, -//! .. -//! } => { +//! Event::RedrawRequested(_) => { //! // 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 //! // by the OS. //! }, diff --git a/src/platform_impl/linux/wayland/event_loop.rs b/src/platform_impl/linux/wayland/event_loop.rs index fba70fa8..97e134ce 100644 --- a/src/platform_impl/linux/wayland/event_loop.rs +++ b/src/platform_impl/linux/wayland/event_loop.rs @@ -526,7 +526,7 @@ impl EventLoop { // send Events cleared { sticky_exit_callback( - crate::event::Event::EventsCleared, + crate::event::Event::MainEventsCleared, &self.window_target, &mut control_flow, &mut callback, @@ -704,7 +704,8 @@ impl EventLoop { ); } 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 { sink.send_window_event(crate::event::WindowEvent::CloseRequested, window.wid); diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index 9a31a266..762066ba 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -534,13 +534,14 @@ impl EventProcessor { ffi::Expose => { let xev: &ffi::XExposeEvent = xev.as_ref(); - let window = xev.window; - let window_id = mkwid(window); + // 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_id = mkwid(window); - callback(Event::WindowEvent { - window_id, - event: WindowEvent::RedrawRequested, - }); + callback(Event::RedrawRequested(window_id)); + } } ffi::KeyPress | ffi::KeyRelease => { diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index 71e538da..a3bdea9c 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -45,7 +45,7 @@ use self::{ }; use crate::{ error::OsError as RootOsError, - event::{Event, StartCause, WindowEvent}, + event::{Event, StartCause}, event_loop::{ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootELW}, platform_impl::{platform::sticky_exit_callback, PlatformSpecificWindowBuilderAttributes}, window::WindowAttributes, @@ -151,6 +151,8 @@ impl EventLoop { xconn.update_cached_wm_info(root); + let pending_redraws: Arc>> = Default::default(); + let mut mod_keymap = ModifierKeymap::new(); mod_keymap.reset_from_x_connection(&xconn); @@ -164,7 +166,7 @@ impl EventLoop { xconn, wm_delete_window, net_wm_ping, - pending_redraws: Default::default(), + pending_redraws: pending_redraws.clone(), }), _marker: ::std::marker::PhantomData, }); @@ -227,7 +229,9 @@ impl EventLoop { if evt.readiness.is_readable() { let mut processor = processor.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 EventLoop { ); } } + // send MainEventsCleared + { + sticky_exit_callback( + crate::event::Event::MainEventsCleared, + &self.target, + &mut control_flow, + &mut callback, + ); + } // Empty the redraw requests { // Release the lock to prevent deadlock @@ -300,20 +313,17 @@ impl EventLoop { for wid in windows { sticky_exit_callback( - Event::WindowEvent { - window_id: crate::window::WindowId(super::WindowId::X(wid)), - event: WindowEvent::RedrawRequested, - }, + Event::RedrawRequested(crate::window::WindowId(super::WindowId::X(wid))), &self.target, &mut control_flow, &mut callback, ); } } - // send Events cleared + // send RedrawEventsCleared { sticky_exit_callback( - crate::event::Event::EventsCleared, + crate::event::Event::RedrawEventsCleared, &self.target, &mut control_flow, &mut callback, @@ -392,8 +402,10 @@ impl EventLoop { fn drain_events(&self) { let mut processor = self.event_processor.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 { @@ -404,9 +416,14 @@ impl EventLoop { fn drain_events( processor: &mut EventProcessor, pending_events: &mut VecDeque>, + pending_redraws: &mut HashSet, ) { let mut callback = |event| { - pending_events.push_back(event); + if let Event::RedrawRequested(crate::window::WindowId(super::WindowId::X(wid))) = event { + pending_redraws.insert(wid); + } else { + pending_events.push_back(event); + } }; // process all pending events