mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 00:36:07 +03:00
apprt/gtk: handle scenario where OpenGL area becomes unrealized
This commit is contained in:
@ -192,9 +192,7 @@ pub fn newWindow(self: *App, parent_: ?*CoreSurface) !void {
|
||||
//
|
||||
// The allocation is owned by the GtkWindow created. It will be
|
||||
// freed when the window is closed.
|
||||
var window = try alloc.create(Window);
|
||||
errdefer alloc.destroy(window);
|
||||
try window.init(self);
|
||||
var window = try Window.create(alloc, self);
|
||||
|
||||
// Add our initial tab
|
||||
try window.newTab(parent_);
|
||||
|
@ -158,6 +158,7 @@ pub fn init(self: *Surface, app: *App, opts: Options) !void {
|
||||
|
||||
// GL events
|
||||
_ = c.g_signal_connect_data(opts.gl_area, "realize", c.G_CALLBACK(>kRealize), self, null, c.G_CONNECT_DEFAULT);
|
||||
_ = c.g_signal_connect_data(opts.gl_area, "unrealize", c.G_CALLBACK(>kUnrealize), self, null, c.G_CONNECT_DEFAULT);
|
||||
_ = c.g_signal_connect_data(opts.gl_area, "destroy", c.G_CALLBACK(>kDestroy), self, null, c.G_CONNECT_DEFAULT);
|
||||
_ = c.g_signal_connect_data(opts.gl_area, "render", c.G_CALLBACK(>kRender), self, null, c.G_CONNECT_DEFAULT);
|
||||
_ = c.g_signal_connect_data(opts.gl_area, "resize", c.G_CALLBACK(>kResize), self, null, c.G_CONNECT_DEFAULT);
|
||||
@ -177,6 +178,16 @@ pub fn init(self: *Surface, app: *App, opts: Options) !void {
|
||||
}
|
||||
|
||||
fn realize(self: *Surface) !void {
|
||||
// If this surface has already been realized, then we don't need to
|
||||
// reinitialize. This can happen if a surface is moved from one GDK surface
|
||||
// to another (i.e. a tab is pulled out into a window).
|
||||
if (self.realized) {
|
||||
// If we have no OpenGL state though, we do need to reinitialize.
|
||||
// We allow the renderer to figure that out
|
||||
try self.core_surface.renderer.displayRealize();
|
||||
return;
|
||||
}
|
||||
|
||||
// Add ourselves to the list of surfaces on the app.
|
||||
try self.app.core_app.addSurface(self);
|
||||
errdefer self.app.core_app.deleteSurface(self);
|
||||
@ -479,6 +490,15 @@ fn gtkRealize(area: *c.GtkGLArea, ud: ?*anyopaque) callconv(.C) void {
|
||||
};
|
||||
}
|
||||
|
||||
/// This is called when the underlying OpenGL resources must be released.
|
||||
/// This is usually due to the OpenGL area changing GDK surfaces.
|
||||
fn gtkUnrealize(area: *c.GtkGLArea, ud: ?*anyopaque) callconv(.C) void {
|
||||
_ = area;
|
||||
|
||||
const self = userdataSelf(ud.?);
|
||||
self.core_surface.renderer.displayUnrealized();
|
||||
}
|
||||
|
||||
/// render signal
|
||||
fn gtkRender(area: *c.GtkGLArea, ctx: *c.GdkGLContext, ud: ?*anyopaque) callconv(.C) c.gboolean {
|
||||
_ = area;
|
||||
|
@ -3,6 +3,7 @@ const Window = @This();
|
||||
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const assert = std.debug.assert;
|
||||
const configpkg = @import("../../config.zig");
|
||||
const font = @import("../../font/main.zig");
|
||||
@ -29,6 +30,20 @@ notebook: *c.GtkNotebook,
|
||||
/// pointer to this because GTK can use it at any time.
|
||||
icon_search_dir: ?[:0]const u8 = null,
|
||||
|
||||
pub fn create(alloc: Allocator, app: *App) !*Window {
|
||||
// Allocate a fixed pointer for our window. We try to minimize
|
||||
// allocations but windows and other GUI requirements are so minimal
|
||||
// compared to the steady-state terminal operation so we use heap
|
||||
// allocation for this.
|
||||
//
|
||||
// The allocation is owned by the GtkWindow created. It will be
|
||||
// freed when the window is closed.
|
||||
var window = try alloc.create(Window);
|
||||
errdefer alloc.destroy(window);
|
||||
try window.init(app);
|
||||
return window;
|
||||
}
|
||||
|
||||
pub fn init(self: *Window, app: *App) !void {
|
||||
// Set up our own state
|
||||
self.* = .{
|
||||
|
Reference in New Issue
Block a user