From 95ff88aa87507fb4497e72288e84b890500a50b1 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Thu, 22 Jun 2023 08:08:53 +0400 Subject: [PATCH] Add `Window::on_present_notify` to ack about drawing That's a way to communicate to winit that you'll present to the window. While it's a no-op for now, it'll be used to throttle drawing. --- CHANGELOG.md | 1 + examples/window.rs | 2 + src/platform_impl/android/mod.rs | 2 + src/platform_impl/ios/window.rs | 2 + src/platform_impl/linux/mod.rs | 12 +++--- src/platform_impl/linux/wayland/window/mod.rs | 5 +++ src/platform_impl/linux/x11/window.rs | 5 +++ src/platform_impl/macos/window.rs | 3 ++ src/platform_impl/orbital/window.rs | 3 ++ src/platform_impl/web/window.rs | 2 + src/platform_impl/windows/window.rs | 3 ++ src/window.rs | 37 +++++++++++++++++++ 12 files changed, 71 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab27f2d981e..7586ddaff34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ And please only add new entries to the top of this list, right below the `# Unre # Unreleased +- Add `Window::pre_present_notify` to notify winit before presenting to the windowing system. - On Android, changed default behavior of Android to ignore volume keys letting the operating system handle them. - On Android, added `EventLoopBuilderExtAndroid::handle_volume_keys` to indicate that the application will handle the volume keys manually. - **Breaking:** Rename `DeviceEventFilter` to `DeviceEvents` reversing the behavior of variants. diff --git a/examples/window.rs b/examples/window.rs index 4a5d8b00682..39914b0ad9f 100644 --- a/examples/window.rs +++ b/examples/window.rs @@ -33,6 +33,8 @@ fn main() { window.request_redraw(); } Event::RedrawRequested(_) => { + // Notify the windowing system that we'll be presenting to the window. + window.pre_present_notify(); fill::fill_window(&window); } _ => (), diff --git a/src/platform_impl/android/mod.rs b/src/platform_impl/android/mod.rs index b48d3acc885..151bad42186 100644 --- a/src/platform_impl/android/mod.rs +++ b/src/platform_impl/android/mod.rs @@ -786,6 +786,8 @@ impl Window { self.redraw_requester.request_redraw() } + pub fn pre_present_notify(&self) {} + pub fn inner_position(&self) -> Result, error::NotSupportedError> { Err(error::NotSupportedError::new()) } diff --git a/src/platform_impl/ios/window.rs b/src/platform_impl/ios/window.rs index f773db5e6b2..744a21f1f9b 100644 --- a/src/platform_impl/ios/window.rs +++ b/src/platform_impl/ios/window.rs @@ -75,6 +75,8 @@ impl Inner { } } + pub fn pre_present_notify(&self) {} + pub fn inner_position(&self) -> Result, NotSupportedError> { unsafe { let safe_area = self.safe_area_screen_space(); diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 03db21ed3e3..90c9426198f 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -541,12 +541,7 @@ impl Window { } } pub fn request_user_attention(&self, request_type: Option) { - match self { - #[cfg(x11_platform)] - Window::X(ref w) => w.request_user_attention(request_type), - #[cfg(wayland_platform)] - Window::Wayland(ref w) => w.request_user_attention(request_type), - } + x11_or_wayland!(match self; Window(w) => w.request_user_attention(request_type)) } #[inline] @@ -554,6 +549,11 @@ impl Window { x11_or_wayland!(match self; Window(w) => w.request_redraw()) } + #[inline] + pub fn pre_present_notify(&self) { + x11_or_wayland!(match self; Window(w) => w.pre_present_notify()) + } + #[inline] pub fn current_monitor(&self) -> Option { match self { diff --git a/src/platform_impl/linux/wayland/window/mod.rs b/src/platform_impl/linux/wayland/window/mod.rs index 26073da3b1f..18b819a9053 100644 --- a/src/platform_impl/linux/wayland/window/mod.rs +++ b/src/platform_impl/linux/wayland/window/mod.rs @@ -274,6 +274,11 @@ impl Window { self.event_loop_awakener.ping(); } + #[inline] + pub fn pre_present_notify(&self) { + // TODO + } + #[inline] pub fn outer_size(&self) -> PhysicalSize { let window_state = self.window_state.lock().unwrap(); diff --git a/src/platform_impl/linux/x11/window.rs b/src/platform_impl/linux/x11/window.rs index adbcf34ebce..f86883db2f9 100644 --- a/src/platform_impl/linux/x11/window.rs +++ b/src/platform_impl/linux/x11/window.rs @@ -1595,6 +1595,11 @@ impl UnownedWindow { .unwrap(); } + #[inline] + pub fn pre_present_notify(&self) { + // TODO timer + } + #[inline] pub fn raw_window_handle(&self) -> RawWindowHandle { let mut window_handle = XlibWindowHandle::empty(); diff --git a/src/platform_impl/macos/window.rs b/src/platform_impl/macos/window.rs index 2ba6acaa7f5..3c85dc93c07 100644 --- a/src/platform_impl/macos/window.rs +++ b/src/platform_impl/macos/window.rs @@ -542,6 +542,9 @@ impl WinitWindow { AppState::queue_redraw(RootWindowId(self.id())); } + #[inline] + pub fn pre_present_notify(&self) {} + pub fn outer_position(&self) -> Result, NotSupportedError> { let frame_rect = self.frame(); let position = LogicalPosition::new( diff --git a/src/platform_impl/orbital/window.rs b/src/platform_impl/orbital/window.rs index 1afe5cdd941..a3748a416e2 100644 --- a/src/platform_impl/orbital/window.rs +++ b/src/platform_impl/orbital/window.rs @@ -166,6 +166,9 @@ impl Window { } } + #[inline] + pub fn pre_present_notify(&self) {} + #[inline] pub fn reset_dead_keys(&self) { // TODO? diff --git a/src/platform_impl/web/window.rs b/src/platform_impl/web/window.rs index 6a379921b55..4ee6597fb9f 100644 --- a/src/platform_impl/web/window.rs +++ b/src/platform_impl/web/window.rs @@ -110,6 +110,8 @@ impl Window { .dispatch(|inner| (inner.register_redraw_request)()); } + pub fn pre_present_notify(&self) {} + pub fn outer_position(&self) -> Result, NotSupportedError> { self.inner.queue(|inner| { Ok(inner diff --git a/src/platform_impl/windows/window.rs b/src/platform_impl/windows/window.rs index 1556c1bbf1c..baac0fd5834 100644 --- a/src/platform_impl/windows/window.rs +++ b/src/platform_impl/windows/window.rs @@ -141,6 +141,9 @@ impl Window { } } + #[inline] + pub fn pre_present_notify(&self) {} + #[inline] pub fn outer_position(&self) -> Result, NotSupportedError> { util::WindowArea::Outer.get_rect(self.hwnd()) diff --git a/src/window.rs b/src/window.rs index 55d9f704f54..4ad04bcbc57 100644 --- a/src/window.rs +++ b/src/window.rs @@ -548,6 +548,43 @@ impl Window { self.window.request_redraw() } + /// Notify the windowing system that you're before presenting to the window. + /// + /// You should call this event after you've done drawing operations, but before you submit + /// the buffer to the display or commit your drawings. Doing so will help winit to properly + /// schedule and do assumptions about its internal state. For example, it could properly + /// throttle [`Event::RedrawRequested`]. + /// + /// ## Example + /// + /// This example illustrates how it looks with OpenGL, but it applies to other graphics + /// APIs and software rendering. + /// + /// ```no_run + /// # use winit::event_loop::EventLoop; + /// # use winit::window::Window; + /// # let mut event_loop = EventLoop::new(); + /// # let window = Window::new(&event_loop).unwrap(); + /// # fn swap_buffers() {} + /// // Do the actual drawing with OpenGL. + /// + /// // Notify winit that we're about to submit buffer to the windowing system. + /// window.pre_present_notify(); + /// + /// // Sumbit buffer to the windowing system. + /// swap_buffers(); + /// ``` + /// + /// ## Platform-specific + /// + /// **Wayland:** - schedules a frame callback to throttle [`Event::RedrawRequested`]. + /// + /// [`Event::RedrawRequested`]: crate::event::Event::RedrawRequested + #[inline] + pub fn pre_present_notify(&self) { + self.window.pre_present_notify(); + } + /// Reset the dead key state of the keyboard. /// /// This is useful when a dead key is bound to trigger an action. Then