From bd053c1bf0a68df4d390f982c04882626c0572c7 Mon Sep 17 00:00:00 2001 From: marc2332 Date: Fri, 31 May 2024 16:53:40 -0400 Subject: [PATCH] feat: add sealed `trait GlutinEventLoop` to abstract over `{,Active}EventLoop` in `winit` 0.30.0 Co-Authored-By: Erich Gubler --- glutin-winit/CHANGELOG.md | 1 + glutin-winit/src/event_loop.rs | 51 ++++++++++++++++++++++++++++++++++ glutin-winit/src/lib.rs | 20 +++++++++---- 3 files changed, 66 insertions(+), 6 deletions(-) create mode 100644 glutin-winit/src/event_loop.rs diff --git a/glutin-winit/CHANGELOG.md b/glutin-winit/CHANGELOG.md index 769c567e2c..5f943fce73 100644 --- a/glutin-winit/CHANGELOG.md +++ b/glutin-winit/CHANGELOG.md @@ -1,6 +1,7 @@ # Unreleased - **Breaking:** Update _winit_ to `0.30`. See [winit's CHANGELOG](https://github.com/rust-windowing/winit/releases/tag/v0.30.0) for more info. +- Add the `GlutinEventLoop` trait to maintain compatibility with the now deprecated `EventLoop` but also support the new `ActiveEventLoop`. - Update `DisplayBuilder` to use `WindowAttributes` instead of `WindowBuilder`. # Version 0.4.2 diff --git a/glutin-winit/src/event_loop.rs b/glutin-winit/src/event_loop.rs new file mode 100644 index 0000000000..13c157a49b --- /dev/null +++ b/glutin-winit/src/event_loop.rs @@ -0,0 +1,51 @@ +use raw_window_handle::{DisplayHandle, HandleError, HasDisplayHandle}; +use winit::error::OsError; +use winit::event_loop::{ActiveEventLoop, EventLoop}; +use winit::window::{Window, WindowAttributes}; + +use crate::private::Sealed; + +/// [`ActiveEventLoop`] is the recommended way to interact with the event +/// loop, but for compatibility purposes [`EventLoop`] is also supported +/// although not recommended anymore as it has been deprecated by Winit. +pub trait GlutinEventLoop: Sealed { + /// Create the window. + /// + /// Possible causes of error include denied permission, incompatible system, + /// and lack of memory. + /// + /// ## Platform-specific + /// + /// - **Web:** The window is created but not inserted into the web page + /// automatically. Please see the web platform module for more + /// information. + fn create_window(&self, window_attributes: WindowAttributes) -> Result; + + /// Get a handle to the display controller of the windowing system. + fn glutin_display_handle(&self) -> Result, HandleError>; +} + +impl Sealed for ActiveEventLoop {} + +impl GlutinEventLoop for ActiveEventLoop { + fn create_window(&self, window_attributes: WindowAttributes) -> Result { + self.create_window(window_attributes) + } + + fn glutin_display_handle(&self) -> Result, HandleError> { + self.display_handle() + } +} + +impl Sealed for EventLoop {} + +impl GlutinEventLoop for EventLoop { + #[allow(deprecated)] + fn create_window(&self, window_attributes: WindowAttributes) -> Result { + self.create_window(window_attributes) + } + + fn glutin_display_handle(&self) -> Result, HandleError> { + self.display_handle() + } +} diff --git a/glutin-winit/src/lib.rs b/glutin-winit/src/lib.rs index 751fb8d692..00b9a8f23d 100644 --- a/glutin-winit/src/lib.rs +++ b/glutin-winit/src/lib.rs @@ -8,8 +8,10 @@ #![deny(missing_docs)] #![cfg_attr(clippy, deny(warnings))] +mod event_loop; mod window; +use event_loop::GlutinEventLoop; pub use window::GlWindow; use std::error::Error; @@ -23,9 +25,8 @@ use glutin::prelude::*; #[cfg(wgl_backend)] use raw_window_handle::HasWindowHandle; -use raw_window_handle::{HasDisplayHandle, RawWindowHandle}; +use raw_window_handle::RawWindowHandle; use winit::error::OsError; -use winit::event_loop::ActiveEventLoop; use winit::window::{Window, WindowAttributes}; #[cfg(glx_backend)] @@ -36,6 +37,13 @@ use winit::platform::x11::WindowAttributesExtX11; #[cfg(all(not(egl_backend), not(glx_backend), not(wgl_backend), not(cgl_backend)))] compile_error!("Please select at least one api backend"); +pub(crate) mod private { + /// Prevent traits from being implemented downstream, since those are used + /// purely for documentation organization and simplify platform api + /// implementation maintenance. + pub trait Sealed {} +} + /// The helper to perform [`Display`] creation and OpenGL platform /// bootstrapping with the help of [`winit`] with little to no platform specific /// code. @@ -88,7 +96,7 @@ impl DisplayBuilder { /// otherwise only builtin functions like `glClear` will be available. pub fn build( mut self, - event_loop: &ActiveEventLoop, + event_loop: &impl GlutinEventLoop, template_builder: ConfigTemplateBuilder, config_picker: Picker, ) -> Result<(Option, Config), Box> @@ -141,7 +149,7 @@ impl DisplayBuilder { } fn create_display( - event_loop: &ActiveEventLoop, + event_loop: &impl GlutinEventLoop, _api_preference: ApiPreference, _raw_window_handle: Option, ) -> Result> { @@ -173,7 +181,7 @@ fn create_display( ApiPreference::FallbackEgl => DisplayApiPreference::WglThenEgl(_raw_window_handle), }; - let handle = event_loop.display_handle()?.as_raw(); + let handle = event_loop.glutin_display_handle()?.as_raw(); unsafe { Ok(Display::new(handle, _preference)?) } } @@ -184,7 +192,7 @@ fn create_display( /// [`Window`]: winit::window::Window /// [`Config`]: glutin::config::Config pub fn finalize_window( - event_loop: &ActiveEventLoop, + event_loop: &impl GlutinEventLoop, mut attributes: WindowAttributes, gl_config: &Config, ) -> Result {