egui_multiwin/
tracked_window.rs

1//! This module covers definition and functionality for an individual window.
2
3use std::num::NonZeroU32;
4
5use egui::NumExt;
6use glutin::context::{NotCurrentContext, PossiblyCurrentContext};
7use glutin::prelude::GlDisplay;
8use glutin::prelude::{NotCurrentGlContext, PossiblyCurrentGlContext};
9use glutin::surface::GlSurface;
10use glutin::surface::WindowSurface;
11use thiserror::Error;
12use winit::event_loop::ControlFlow;
13
14/// A holder of context and related items
15pub struct ContextHolder<T> {
16    /// The context being held
17    context: T,
18    /// The window
19    pub window: winit::window::Window,
20    /// The window surface
21    ws: glutin::surface::Surface<WindowSurface>,
22    /// The display
23    display: glutin::display::Display,
24    /// The options for the display
25    options: TrackedWindowOptions,
26    /// The last control flow of the window
27    pub control_flow: Option<ControlFlow>,
28}
29
30impl<T> ContextHolder<T> {
31    /// Create a new context holder
32    pub fn new(
33        context: T,
34        window: winit::window::Window,
35        ws: glutin::surface::Surface<WindowSurface>,
36        display: glutin::display::Display,
37        options: TrackedWindowOptions,
38    ) -> Self {
39        Self {
40            context,
41            window,
42            ws,
43            display,
44            options,
45            control_flow: Some(ControlFlow::Poll),
46        }
47    }
48}
49impl<T> ContextHolder<T> {
50    /// Get the window handle
51    pub fn window(&self) -> &winit::window::Window {
52        &self.window
53    }
54}
55
56impl ContextHolder<PossiblyCurrentContext> {
57    /// Call swap_buffers. linux targets have vsync specifically disabled because it causes problems with hidden windows.
58    pub fn swap_buffers(&self) -> glutin::error::Result<()> {
59        if self.options.vsync {
60            let _e = self.ws.set_swap_interval(
61                &self.context,
62                glutin::surface::SwapInterval::Wait(NonZeroU32::MIN),
63            );
64        } else {
65            let _e = self
66                .ws
67                .set_swap_interval(&self.context, glutin::surface::SwapInterval::DontWait);
68        }
69        self.ws.swap_buffers(&self.context)
70    }
71
72    /// Resize the window to the specified size. The size cannot be zero in either dimension.
73    pub fn resize(&self, size: winit::dpi::PhysicalSize<u32>) {
74        let w = size.width;
75        let h = size.height;
76        self.ws.resize(
77            &self.context,
78            NonZeroU32::new(w.at_least(1)).unwrap(),
79            NonZeroU32::new(h.at_least(1)).unwrap(),
80        )
81    }
82
83    /// Make a possibly current context current
84    pub fn make_current(&self) -> glutin::error::Result<()> {
85        self.context.make_current(&self.ws)
86    }
87
88    /// convenience function to call get_proc_address on the display of this struct
89    pub fn get_proc_address(&self, s: &str) -> *const std::ffi::c_void {
90        let cs: *const std::ffi::c_char = s.as_ptr().cast();
91        let cst = unsafe { std::ffi::CStr::from_ptr(cs) };
92        self.display.get_proc_address(cst)
93    }
94}
95
96impl ContextHolder<NotCurrentContext> {
97    /// Transforms a not current context into a possibly current context
98    pub fn make_current(
99        self,
100    ) -> Result<ContextHolder<PossiblyCurrentContext>, glutin::error::Error> {
101        let c = self.context.make_current(&self.ws).unwrap();
102        let s = ContextHolder::<PossiblyCurrentContext> {
103            context: c,
104            window: self.window,
105            ws: self.ws,
106            display: self.display,
107            options: self.options,
108            control_flow: self.control_flow,
109        };
110        Ok(s)
111    }
112}
113
114/// The options for a window.
115#[derive(Copy, Clone)]
116pub struct TrackedWindowOptions {
117    /// Should the window be vsynced. Check github issues to see if this property actually does what it is supposed to.
118    pub vsync: bool,
119    /// Optionally sets the shader version for the window.
120    pub shader: Option<egui_glow::ShaderVersion>,
121}
122
123#[derive(Error, Debug)]
124/// Enumerates the kinds of errors that display creation can have.
125pub enum DisplayCreationError {}