1 | use std::num::NonZeroU32; |
2 | |
3 | use glutin::context::PossiblyCurrentContext; |
4 | use glutin::surface::{ |
5 | GlSurface, ResizeableSurface, Surface, SurfaceAttributes, SurfaceAttributesBuilder, |
6 | SurfaceTypeTrait, WindowSurface, |
7 | }; |
8 | use raw_window_handle::{HandleError, HasWindowHandle}; |
9 | use winit::window::Window; |
10 | |
11 | /// [`Window`] extensions for working with [`glutin`] surfaces. |
12 | pub trait GlWindow { |
13 | /// Build the surface attributes suitable to create a window surface. |
14 | /// |
15 | /// # Panics |
16 | /// Panics if either window inner dimension is zero. |
17 | /// |
18 | /// # Example |
19 | /// ```no_run |
20 | /// use glutin_winit::GlWindow; |
21 | /// # let winit_window: winit::window::Window = unimplemented!(); |
22 | /// |
23 | /// let attrs = winit_window.build_surface_attributes(<_>::default()); |
24 | /// ``` |
25 | fn build_surface_attributes( |
26 | &self, |
27 | builder: SurfaceAttributesBuilder<WindowSurface>, |
28 | ) -> Result<SurfaceAttributes<WindowSurface>, HandleError>; |
29 | |
30 | /// Resize the surface to the window inner size. |
31 | /// |
32 | /// No-op if either window size is zero. |
33 | /// |
34 | /// # Example |
35 | /// ```no_run |
36 | /// use glutin_winit::GlWindow; |
37 | /// # use glutin::surface::{Surface, WindowSurface}; |
38 | /// # let winit_window: winit::window::Window = unimplemented!(); |
39 | /// # let (gl_surface, gl_context): (Surface<WindowSurface>, _) = unimplemented!(); |
40 | /// |
41 | /// winit_window.resize_surface(&gl_surface, &gl_context); |
42 | /// ``` |
43 | fn resize_surface( |
44 | &self, |
45 | surface: &Surface<impl SurfaceTypeTrait + ResizeableSurface>, |
46 | context: &PossiblyCurrentContext, |
47 | ); |
48 | } |
49 | |
50 | impl GlWindow for Window { |
51 | fn build_surface_attributes( |
52 | &self, |
53 | builder: SurfaceAttributesBuilder<WindowSurface>, |
54 | ) -> Result<SurfaceAttributes<WindowSurface>, HandleError> { |
55 | let (w: NonZero, h: NonZero) = self.inner_size().non_zero().expect(msg:"invalid zero inner size" ); |
56 | let handle: RawWindowHandle = self.window_handle()?.as_raw(); |
57 | Ok(builder.build(handle, width:w, height:h)) |
58 | } |
59 | |
60 | fn resize_surface( |
61 | &self, |
62 | surface: &Surface<impl SurfaceTypeTrait + ResizeableSurface>, |
63 | context: &PossiblyCurrentContext, |
64 | ) { |
65 | if let Some((w: NonZero, h: NonZero)) = self.inner_size().non_zero() { |
66 | surface.resize(context, width:w, height:h) |
67 | } |
68 | } |
69 | } |
70 | |
71 | /// [`winit::dpi::PhysicalSize<u32>`] non-zero extensions. |
72 | trait NonZeroU32PhysicalSize { |
73 | /// Converts to non-zero `(width, height)`. |
74 | fn non_zero(self) -> Option<(NonZeroU32, NonZeroU32)>; |
75 | } |
76 | impl NonZeroU32PhysicalSize for winit::dpi::PhysicalSize<u32> { |
77 | fn non_zero(self) -> Option<(NonZeroU32, NonZeroU32)> { |
78 | let w: NonZero = NonZeroU32::new(self.width)?; |
79 | let h: NonZero = NonZeroU32::new(self.height)?; |
80 | Some((w, h)) |
81 | } |
82 | } |
83 | |