I am able to successfully create a GTK window with a GLArea component in it. When the GLArea is the only component in the window, the window can be resized normally.
use gtk::prelude::*;
use glium::Surface;
use std::os::raw::c_void;
// This struct taken from https://github.com/PonasKovas/gtk-glium
struct GLAreaBackend {
glarea: gtk::GLArea,
}
unsafe impl glium::backend::Backend for GLAreaBackend {
fn swap_buffers(&self) -> Result<(), glium::SwapBuffersError> {
// GTK swaps the buffers after each "render" signal itself
Ok(())
}
unsafe fn get_proc_address(&self, symbol: &str) -> *const c_void {
gl_loader::get_proc_address(symbol) as *const _
}
fn get_framebuffer_dimensions(&self) -> (u32, u32) {
(self.glarea.allocated_width().try_into().unwrap(),
self.glarea.allocated_height().try_into().unwrap())
}
fn is_current(&self) -> bool {
// GTK makes it current itself on each "render" signal
true
}
unsafe fn make_current(&self) {
self.glarea.make_current();
}
}
impl GLAreaBackend {
fn new(glarea: gtk::GLArea) -> Self {
Self { glarea }
}
}
fn main() {
let application = gtk::Application::builder().build();
application.connect_activate(|app| {
let window = gtk::ApplicationWindow::builder()
.application(app)
.title("test app")
.default_width(640)
.default_height(480)
.build();
gl_loader::init_gl();
let gl_area = gtk::GLArea::builder()
.expand(true)
.halign(gtk::Align::Fill)
.valign(gtk::Align::Fill)
.auto_render(true)
.has_alpha(false)
.build();
let button = gtk::Button::with_label("press me!");
let container = gtk::Box::new(gtk::Orientation::Vertical, 0);
container.pack_start(&gl_area, true, true, 0);
//container.pack_start(&button, false, false, 0);
window.add(&container);
window.show_all();
// from gtk-glium
let gl_context = unsafe {
glium::backend::Context::new(GLAreaBackend::new(gl_area.clone()),
true,
glium::debug::DebugCallbackBehavior::DebugMessageOnError).unwrap()
};
gl_area.connect_render(move |_, _| {
let mut frame = glium::Frame::new(gl_context.clone(), gl_context.get_framebuffer_dimensions());
frame.clear_color(1.0, 1.0, 0.5, 1.0);
frame.finish().unwrap();
Inhibit(true)
});
});
application.run();
}
However, uncommenting then line //container.pack_start(&button, false, false, 0);
causes the window to not render properly after being resized:
Does anyone know how to fix this?
EDIT: The problem persists without any OpenGL calls. The following simple example has the same issue. I am using Ubuntu 20.04.
use gtk::prelude::*;
fn main() {
let application = gtk::Application::builder().build();
application.connect_activate(|app| {
let window = gtk::ApplicationWindow::builder()
.application(app)
.default_width(640)
.default_height(480)
.build();
let gl_area = gtk::GLArea::builder()
.auto_render(false)
.build();
let button = gtk::Button::with_label("press me!");
let container = gtk::Box::new(gtk::Orientation::Vertical, 0);
container.pack_start(&gl_area, true, true, 0);
//container.pack_start(&button, false, false, 0);
window.add(&container);
window.show_all();
});
application.run();
}
The problem appears to be a minor bug in the GTK3 library, as it persists when using C and no OpenGL calls. Upgrading my project to GTK4 fixed it.
I was able to find the solution at https://gitlab.gnome.org/GNOME/gtk/-/issues/1298, in particular the comment "it reproduces with gtk3-demo under X11, not with gtk4-demo."