diff --git a/src/win/window.rs b/src/win/window.rs index 2af1abed..a9b28ff8 100644 --- a/src/win/window.rs +++ b/src/win/window.rs @@ -19,6 +19,8 @@ use winapi::um::winuser::{ use std::cell::{Cell, RefCell}; use std::collections::VecDeque; use std::ffi::{c_void, OsStr}; +use std::fmt; +use std::fmt::{Debug, Formatter}; use std::marker::PhantomData; use std::os::windows::ffi::OsStrExt; use std::ptr::null_mut; @@ -510,17 +512,30 @@ impl WindowState { ) }; } + WindowTask::Custom(t) => { + t.0(); + } } } } /// Tasks that must be deferred until the end of [`wnd_proc()`] to avoid reentrant `WindowState` /// borrows. See the docstring on [`WindowState::deferred_tasks`] for more information. -#[derive(Debug, Clone)] +#[derive(Debug)] enum WindowTask { /// Resize the window to the given size. The size is in logical pixels. DPI scaling is applied /// automatically. Resize(Size), + /// User-defined task. + Custom(CustomTask), +} + +struct CustomTask(Box); + +impl Debug for CustomTask { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + f.debug_struct("CustomTask").finish() + } } pub struct Window<'a> { @@ -749,6 +764,11 @@ impl Window<'_> { self.state.deferred_tasks.borrow_mut().push_back(task); } + pub fn defer(&mut self, task: impl Fn() + 'static) { + let task = WindowTask::Custom(CustomTask(Box::new(task))); + self.state.deferred_tasks.borrow_mut().push_back(task); + } + #[cfg(feature = "opengl")] pub fn gl_context(&self) -> Option<&GlContext> { self.state.gl_context.as_ref() diff --git a/src/window.rs b/src/window.rs index c0ef1ac8..3ca1e46c 100644 --- a/src/window.rs +++ b/src/window.rs @@ -115,6 +115,14 @@ impl<'a> Window<'a> { self.window.resize(size); } + /// Defers execution of the given task until the end of main loop cycle. + /// + /// This is sometimes necessary to avoid mutably borrowing internal fields more than once. + #[cfg(windows)] + pub fn defer(&mut self, task: impl Fn() + 'static) { + self.window.defer(task); + } + /// If provided, then an OpenGL context will be created for this window. You'll be able to /// access this context through [crate::Window::gl_context]. #[cfg(feature = "opengl")]