mirror of
https://github.com/eliasstepanik/imgui-rs.git
synced 2026-01-16 07:58:33 +00:00
Do not allow to create coexisting instances of WindowDrawList
At run time, the environment checks that at most one instance of
WindowDrawList exists using a static boolean: WINDOW_DRAW_LIST_LOADED.
If two WindowDrawList could exist at the same time, there would be
several instances of the same `*mut ImDrawList`, which could lead
to unfathomable bad things.
When a WindowDrawList is created, WINDOW_DRAW_LIST_LOADED is set to
true. And when it is dropped, WINDOW_DRAW_LIST_LOADED is set to false.
Creating a new WindowDrawList while WINDOW_DRAW_LIST_LOADED is true
causes a panic.
AtomicBool could have been used instead of a bool for
WINDOW_DRAW_LIST_LOADED. Though it allows to avoid the use of `unsafe { }`,
the construct we are doing is already inherently unsafe.
WindowDrawList and Ui are !Send and !Sync, so they cannot anyway be shared
among threads.
So we'd better be explicit and use an unsafe block with a normal bool.
This commit is contained in:
parent
082d5e47f9
commit
454e98037e
15
src/lib.rs
15
src/lib.rs
@ -1281,6 +1281,21 @@ impl<'ui> Ui<'ui> {
|
||||
/// // Continue drawing ...
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// This function will panic if several instances of [`WindowDrawList`]
|
||||
/// coexist. Before a new instance is got, a previous instance should be
|
||||
/// dropped.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use imgui::*;
|
||||
/// fn custom_draw(ui: &Ui) {
|
||||
/// let draw_list = ui.get_window_draw_list();
|
||||
/// // Draw something...
|
||||
///
|
||||
/// // This second call will panic!
|
||||
/// let draw_list = ui.get_window_draw_list();
|
||||
/// }
|
||||
/// ```
|
||||
pub fn get_window_draw_list(&'ui self) -> WindowDrawList<'ui> {
|
||||
WindowDrawList::new(self)
|
||||
}
|
||||
|
||||
@ -54,6 +54,10 @@ pub trait DrawAPI {
|
||||
}
|
||||
|
||||
/// Object implementing the custom draw API.
|
||||
///
|
||||
/// Called from [`Ui::get_window_draw_list`]. No more than one instance of this
|
||||
/// structure can live in a program at the same time.
|
||||
/// The program will panic on creating a second instance.
|
||||
pub struct WindowDrawList<'ui> {
|
||||
draw_list: *mut ImDrawList,
|
||||
_phantom: PhantomData<&'ui Ui<'ui>>,
|
||||
@ -63,8 +67,22 @@ impl<'ui> DrawAPI for WindowDrawList<'ui> {
|
||||
fn draw_list(&self) -> *mut ImDrawList { self.draw_list }
|
||||
}
|
||||
|
||||
static mut WINDOW_DRAW_LIST_LOADED: bool = false;
|
||||
|
||||
impl<'ui> Drop for WindowDrawList<'ui> {
|
||||
fn drop(&mut self) {
|
||||
unsafe { WINDOW_DRAW_LIST_LOADED = false; }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ui> WindowDrawList<'ui> {
|
||||
pub(crate) fn new(_: &Ui<'ui>) -> Self {
|
||||
unsafe {
|
||||
if WINDOW_DRAW_LIST_LOADED {
|
||||
panic!("WindowDrawList is already loaded! You can only load one instance of it!")
|
||||
}
|
||||
WINDOW_DRAW_LIST_LOADED = true;
|
||||
}
|
||||
Self {
|
||||
draw_list: unsafe { sys::igGetWindowDrawList() },
|
||||
_phantom: PhantomData,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user