Fixed crash on window docking on linux

This commit is contained in:
Robin Quint 2022-12-22 14:44:26 +01:00
parent 070f56f1d1
commit f430041018
3 changed files with 36 additions and 21 deletions

View File

@ -1,3 +1,5 @@
#version 330
in vec2 v2f_UV; in vec2 v2f_UV;
in vec4 v2f_Color; in vec4 v2f_Color;

View File

@ -52,13 +52,15 @@ enum ViewportEvent {
pub struct Renderer { pub struct Renderer {
gl_objects: GlObjects, gl_objects: GlObjects,
glutin_config: Option<glutin::config::Config>, glutin_config: Option<glutin::config::Config>,
/// The tuple members have to stay in exactly this order
/// to ensure that surface, context and window are dropped in this order
extra_windows: HashMap< extra_windows: HashMap<
Id, Id,
( (
Window,
Option<NotCurrentContext>,
Surface<WindowSurface>,
GlObjects, GlObjects,
Surface<WindowSurface>,
Option<NotCurrentContext>,
Window,
), ),
>, >,
event_queue: Rc<RefCell<VecDeque<ViewportEvent>>>, event_queue: Rc<RefCell<VecDeque<ViewportEvent>>>,
@ -321,7 +323,7 @@ impl Renderer {
(main_window, imgui.main_viewport_mut()) (main_window, imgui.main_viewport_mut())
} else { } else {
if let Some((id, wnd)) = if let Some((id, wnd)) =
self.extra_windows.iter().find_map(|(id, (wnd, _, _, _))| { self.extra_windows.iter().find_map(|(id, (_, _, _, wnd))| {
if wnd.id() == window_id { if wnd.id() == window_id {
Some((*id, wnd)) Some((*id, wnd))
} else { } else {
@ -472,27 +474,27 @@ impl Renderer {
self.extra_windows.remove(&id); self.extra_windows.remove(&id);
} }
ViewportEvent::SetPos(id, pos) => { ViewportEvent::SetPos(id, pos) => {
if let Some((wnd, _, _, _)) = self.extra_windows.get(&id) { if let Some((_, _, _, wnd)) = self.extra_windows.get(&id) {
wnd.set_outer_position(PhysicalPosition::new(pos[0], pos[1])); wnd.set_outer_position(PhysicalPosition::new(pos[0], pos[1]));
} }
} }
ViewportEvent::SetSize(id, size) => { ViewportEvent::SetSize(id, size) => {
if let Some((wnd, _, _, _)) = self.extra_windows.get(&id) { if let Some((_, _, _, wnd)) = self.extra_windows.get(&id) {
wnd.set_inner_size(PhysicalSize::new(size[0], size[1])); wnd.set_inner_size(PhysicalSize::new(size[0], size[1]));
} }
} }
ViewportEvent::SetVisible(id) => { ViewportEvent::SetVisible(id) => {
if let Some((wnd, _, _, _)) = self.extra_windows.get(&id) { if let Some((_, _, _, wnd)) = self.extra_windows.get(&id) {
wnd.set_visible(true); wnd.set_visible(true);
} }
} }
ViewportEvent::SetFocus(id) => { ViewportEvent::SetFocus(id) => {
if let Some((wnd, _, _, _)) = self.extra_windows.get(&id) { if let Some((_, _, _, wnd)) = self.extra_windows.get(&id) {
wnd.focus_window(); wnd.focus_window();
} }
} }
ViewportEvent::SetTitle(id, title) => { ViewportEvent::SetTitle(id, title) => {
if let Some((wnd, _, _, _)) = self.extra_windows.get(&id) { if let Some((_, _, _, wnd)) = self.extra_windows.get(&id) {
wnd.set_title(&title); wnd.set_title(&title);
} }
} }
@ -509,10 +511,10 @@ impl Renderer {
glow: &glow::Context, glow: &glow::Context,
) -> Result< ) -> Result<
( (
Window,
Option<NotCurrentContext>,
Surface<WindowSurface>,
GlObjects, GlObjects,
Surface<WindowSurface>,
Option<NotCurrentContext>,
Window,
), ),
RendererError, RendererError,
> { > {
@ -572,10 +574,10 @@ impl Renderer {
GlObjects::new(self.font_width, self.font_height, &self.font_pixels, glow)?; GlObjects::new(self.font_width, self.font_height, &self.font_pixels, glow)?;
Ok(( Ok((
window,
Some(context.make_not_current().unwrap()),
surface,
gl_objects, gl_objects,
surface,
Some(context.make_not_current().unwrap()),
window,
)) ))
} }
@ -593,7 +595,7 @@ impl Renderer {
glow: &glow::Context, glow: &glow::Context,
imgui: &mut imgui::Context, imgui: &mut imgui::Context,
) -> Result<(), RendererError> { ) -> Result<(), RendererError> {
for (id, (wnd, context, surface, gl_objects)) in &mut self.extra_windows { for (id, (gl_objects, surface, context, wnd)) in &mut self.extra_windows {
if let Some(viewport) = imgui.viewport_by_id(*id) { if let Some(viewport) = imgui.viewport_by_id(*id) {
let current_context = context let current_context = context
.take() .take()
@ -689,12 +691,21 @@ impl Renderer {
for cmd in list.commands() { for cmd in list.commands() {
match cmd { match cmd {
imgui::DrawCmd::Elements { count, cmd_params } => { imgui::DrawCmd::Elements { count, cmd_params } => {
let clip_x1 = (cmd_params.clip_rect[0] - draw_data.display_pos[0]) as i32; let clip_x1 =
let clip_y1 = (cmd_params.clip_rect[1] - draw_data.display_pos[1]) as i32; (cmd_params.clip_rect[0] - draw_data.display_pos[0]) as i32;
let clip_x2 = (cmd_params.clip_rect[2] - draw_data.display_pos[0]) as i32; let clip_y1 =
let clip_y2 = (cmd_params.clip_rect[3] - draw_data.display_pos[1]) as i32; (cmd_params.clip_rect[1] - draw_data.display_pos[1]) as i32;
let clip_x2 =
(cmd_params.clip_rect[2] - draw_data.display_pos[0]) as i32;
let clip_y2 =
(cmd_params.clip_rect[3] - draw_data.display_pos[1]) as i32;
glow.scissor(clip_x1, window_size.height as i32 - clip_y2, clip_x2 - clip_x1, clip_y2 - clip_y1); glow.scissor(
clip_x1,
window_size.height as i32 - clip_y2,
clip_x2 - clip_x1,
clip_y2 - clip_y1,
);
glow.draw_elements_base_vertex( glow.draw_elements_base_vertex(
glow::TRIANGLES, glow::TRIANGLES,
count as i32, count as i32,

View File

@ -1,3 +1,5 @@
#version 330
layout(location = 0) in vec2 in_Position; layout(location = 0) in vec2 in_Position;
layout(location = 1) in vec2 in_UV; layout(location = 1) in vec2 in_UV;
layout(location = 2) in vec4 in_Color; layout(location = 2) in vec4 in_Color;