Skip to content

Commit

Permalink
RustAudio#143 Windows: Add public defer method
Browse files Browse the repository at this point in the history
  • Loading branch information
helgoboss committed Apr 16, 2023
1 parent c129b12 commit 6a7c84e
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 1 deletion.
22 changes: 21 additions & 1 deletion src/win/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<dyn Fn() + 'static>);

impl Debug for CustomTask {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.debug_struct("CustomTask").finish()
}
}

pub struct Window<'a> {
Expand Down Expand Up @@ -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()
Expand Down
8 changes: 8 additions & 0 deletions src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")]
Expand Down

0 comments on commit 6a7c84e

Please sign in to comment.