mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-23 20:26:09 +03:00
apprt/gtk-ng: hook up surface initialization
This commit is contained in:
26
src/App.zig
26
src/App.zig
@ -154,7 +154,7 @@ pub fn tick(self: *App, rt_app: *apprt.App) !void {
|
||||
pub fn updateConfig(self: *App, rt_app: *apprt.App, config: *const Config) !void {
|
||||
// Go through and update all of the surface configurations.
|
||||
for (self.surfaces.items) |surface| {
|
||||
try surface.core_surface.handleMessage(.{ .change_config = config });
|
||||
try surface.core().handleMessage(.{ .change_config = config });
|
||||
}
|
||||
|
||||
// Apply our conditional state. If we fail to apply the conditional state
|
||||
@ -190,7 +190,7 @@ pub fn addSurface(
|
||||
// Since we have non-zero surfaces, we can cancel the quit timer.
|
||||
// It is up to the apprt if there is a quit timer at all and if it
|
||||
// should be canceled.
|
||||
_ = rt_surface.app.performAction(
|
||||
_ = rt_surface.rtApp().performAction(
|
||||
.app,
|
||||
.quit_timer,
|
||||
.stop,
|
||||
@ -207,7 +207,7 @@ pub fn deleteSurface(self: *App, rt_surface: *apprt.Surface) void {
|
||||
// just let focused surface be but the allocator was reusing addresses
|
||||
// after free and giving false positives, so we must clear it.
|
||||
if (self.focused_surface) |focused| {
|
||||
if (focused == &rt_surface.core_surface) {
|
||||
if (focused == rt_surface.core()) {
|
||||
self.focused_surface = null;
|
||||
}
|
||||
}
|
||||
@ -224,7 +224,7 @@ pub fn deleteSurface(self: *App, rt_surface: *apprt.Surface) void {
|
||||
|
||||
// If we have no surfaces, we can start the quit timer. It is up to the
|
||||
// apprt to determine if this is necessary.
|
||||
if (self.surfaces.items.len == 0) _ = rt_surface.app.performAction(
|
||||
if (self.surfaces.items.len == 0) _ = rt_surface.rtApp().performAction(
|
||||
.app,
|
||||
.quit_timer,
|
||||
.start,
|
||||
@ -245,7 +245,7 @@ pub fn focusedSurface(self: *const App) ?*Surface {
|
||||
/// the apprt to call this.
|
||||
pub fn needsConfirmQuit(self: *const App) bool {
|
||||
for (self.surfaces.items) |v| {
|
||||
if (v.core_surface.needsConfirmQuit()) return true;
|
||||
if (v.core().needsConfirmQuit()) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -287,12 +287,12 @@ pub fn focusSurface(self: *App, surface: *Surface) void {
|
||||
}
|
||||
|
||||
fn redrawSurface(self: *App, rt_app: *apprt.App, surface: *apprt.Surface) void {
|
||||
if (!self.hasSurface(&surface.core_surface)) return;
|
||||
if (!self.hasRtSurface(surface)) return;
|
||||
rt_app.redrawSurface(surface);
|
||||
}
|
||||
|
||||
fn redrawInspector(self: *App, rt_app: *apprt.App, surface: *apprt.Surface) void {
|
||||
if (!self.hasSurface(&surface.core_surface)) return;
|
||||
if (!self.hasRtSurface(surface)) return;
|
||||
rt_app.redrawInspector(surface);
|
||||
}
|
||||
|
||||
@ -482,7 +482,7 @@ pub fn performAllAction(
|
||||
// Surface-scoped actions are performed on all surfaces. Errors
|
||||
// are logged but processing continues.
|
||||
.surface => for (self.surfaces.items) |surface| {
|
||||
_ = surface.core_surface.performBindingAction(action) catch |err| {
|
||||
_ = surface.core().performBindingAction(action) catch |err| {
|
||||
log.warn("error performing binding action on surface ptr={X} err={}", .{
|
||||
@intFromPtr(surface),
|
||||
err,
|
||||
@ -507,7 +507,15 @@ fn surfaceMessage(self: *App, surface: *Surface, msg: apprt.surface.Message) !vo
|
||||
|
||||
fn hasSurface(self: *const App, surface: *const Surface) bool {
|
||||
for (self.surfaces.items) |v| {
|
||||
if (&v.core_surface == surface) return true;
|
||||
if (v.core() == surface) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
fn hasRtSurface(self: *const App, surface: *apprt.Surface) bool {
|
||||
for (self.surfaces.items) |v| {
|
||||
if (v == surface) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -1738,7 +1738,10 @@ pub fn selectionInfo(self: *const Surface) ?apprt.Selection {
|
||||
/// Returns the pwd of the terminal, if any. This is always copied because
|
||||
/// the pwd can change at any point from termio. If we are calling from the IO
|
||||
/// thread you should just check the terminal directly.
|
||||
pub fn pwd(self: *const Surface, alloc: Allocator) !?[]const u8 {
|
||||
pub fn pwd(
|
||||
self: *const Surface,
|
||||
alloc: Allocator,
|
||||
) Allocator.Error!?[]const u8 {
|
||||
self.renderer_state.mutex.lock();
|
||||
defer self.renderer_state.mutex.unlock();
|
||||
const terminal_pwd = self.io.terminal.getPwd() orelse return null;
|
||||
|
@ -601,6 +601,14 @@ pub const Surface = struct {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn core(self: *Surface) *CoreSurface {
|
||||
return &self.core_surface;
|
||||
}
|
||||
|
||||
pub fn rtApp(self: *const Surface) *App {
|
||||
return self.app;
|
||||
}
|
||||
|
||||
pub fn close(self: *const Surface, process_alive: bool) void {
|
||||
const func = self.app.opts.close_surface orelse {
|
||||
log.info("runtime embedder does not support closing a surface", .{});
|
||||
|
@ -19,6 +19,11 @@ const adw_version = @import("adw_version.zig");
|
||||
|
||||
const log = std.log.scoped(.gtk);
|
||||
|
||||
/// This is detected by the Renderer, in which case it sends a `redraw_surface`
|
||||
/// message so that we can call `drawFrame` ourselves from the app thread,
|
||||
/// because GTK's `GLArea` does not support drawing from a different thread.
|
||||
pub const must_draw_from_app_thread = true;
|
||||
|
||||
/// The GObject Application instance
|
||||
app: *Application,
|
||||
|
||||
@ -48,6 +53,11 @@ pub fn terminate(self: *App) void {
|
||||
self.app.deinit();
|
||||
}
|
||||
|
||||
/// Called by CoreApp to wake up the event loop.
|
||||
pub fn wakeup(self: *App) void {
|
||||
self.app.wakeup();
|
||||
}
|
||||
|
||||
pub fn performAction(
|
||||
self: *App,
|
||||
target: apprt.Target,
|
||||
|
@ -1,41 +1,62 @@
|
||||
const Surface = @This();
|
||||
const Self = @This();
|
||||
|
||||
const std = @import("std");
|
||||
const apprt = @import("../../apprt.zig");
|
||||
const CoreSurface = @import("../../Surface.zig");
|
||||
const ApprtApp = @import("App.zig");
|
||||
const Application = @import("class/application.zig").Application;
|
||||
const Surface = @import("class/surface.zig").Surface;
|
||||
|
||||
core_surface: CoreSurface,
|
||||
/// The GObject Surface
|
||||
surface: *Surface,
|
||||
|
||||
pub fn deinit(self: *Surface) void {
|
||||
pub fn deinit(self: *Self) void {
|
||||
_ = self;
|
||||
}
|
||||
|
||||
pub fn close(self: *Surface, process_active: bool) void {
|
||||
pub fn core(self: *Self) *CoreSurface {
|
||||
// This asserts the non-optional because libghostty should only
|
||||
// be calling this for initialized surfaces.
|
||||
return self.surface.core().?;
|
||||
}
|
||||
|
||||
pub fn rtApp(self: *Self) *ApprtApp {
|
||||
_ = self;
|
||||
return Application.default().rt();
|
||||
}
|
||||
|
||||
pub fn close(self: *Self, process_active: bool) void {
|
||||
_ = self;
|
||||
_ = process_active;
|
||||
}
|
||||
|
||||
pub fn shouldClose(self: *Surface) bool {
|
||||
pub fn shouldClose(self: *Self) bool {
|
||||
_ = self;
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn getTitle(self: *Surface) ?[:0]const u8 {
|
||||
pub fn getTitle(self: *Self) ?[:0]const u8 {
|
||||
_ = self;
|
||||
return null;
|
||||
}
|
||||
|
||||
pub fn getContentScale(self: *const Surface) !apprt.ContentScale {
|
||||
pub fn getContentScale(self: *const Self) !apprt.ContentScale {
|
||||
_ = self;
|
||||
return .{ .x = 1, .y = 1 };
|
||||
}
|
||||
|
||||
pub fn getCursorPos(self: *const Surface) !apprt.CursorPos {
|
||||
pub fn getSize(self: *const Self) !apprt.SurfaceSize {
|
||||
_ = self;
|
||||
return .{ .width = 800, .height = 600 };
|
||||
}
|
||||
|
||||
pub fn getCursorPos(self: *const Self) !apprt.CursorPos {
|
||||
_ = self;
|
||||
return .{ .x = 0, .y = 0 };
|
||||
}
|
||||
|
||||
pub fn clipboardRequest(
|
||||
self: *Surface,
|
||||
self: *Self,
|
||||
clipboard_type: apprt.Clipboard,
|
||||
state: apprt.ClipboardRequest,
|
||||
) !void {
|
||||
@ -45,7 +66,7 @@ pub fn clipboardRequest(
|
||||
}
|
||||
|
||||
pub fn setClipboardString(
|
||||
self: *Surface,
|
||||
self: *Self,
|
||||
val: [:0]const u8,
|
||||
clipboard_type: apprt.Clipboard,
|
||||
confirm: bool,
|
||||
@ -55,3 +76,7 @@ pub fn setClipboardString(
|
||||
_ = clipboard_type;
|
||||
_ = confirm;
|
||||
}
|
||||
|
||||
pub fn defaultTermioEnv(self: *Self) !std.process.EnvMap {
|
||||
return try self.surface.defaultTermioEnv();
|
||||
}
|
||||
|
@ -476,6 +476,25 @@ pub const Application = extern struct {
|
||||
return self.private().config;
|
||||
}
|
||||
|
||||
/// Returns the core app associated with this application. This is
|
||||
/// not a reference-counted type so you should not store this.
|
||||
pub fn core(self: *Self) *CoreApp {
|
||||
return self.private().core_app;
|
||||
}
|
||||
|
||||
/// Returns the apprt application associated with this application.
|
||||
pub fn rt(self: *Self) *ApprtApp {
|
||||
return self.private().rt_app;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Libghostty Callbacks
|
||||
|
||||
pub fn wakeup(self: *Self) void {
|
||||
_ = self;
|
||||
glib.MainContext.wakeup(null);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Virtual Methods
|
||||
|
||||
|
@ -1,11 +1,16 @@
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const adw = @import("adw");
|
||||
const gobject = @import("gobject");
|
||||
const gtk = @import("gtk");
|
||||
|
||||
const apprt = @import("../../../apprt.zig");
|
||||
const internal_os = @import("../../../os/main.zig");
|
||||
const renderer = @import("../../../renderer.zig");
|
||||
const CoreSurface = @import("../../../Surface.zig");
|
||||
const gresource = @import("../build/gresource.zig");
|
||||
const adw_version = @import("../adw_version.zig");
|
||||
const ApprtSurface = @import("../Surface.zig");
|
||||
const Common = @import("../class.zig").Common;
|
||||
const Application = @import("application.zig").Application;
|
||||
const Config = @import("config.zig").Config;
|
||||
@ -54,6 +59,20 @@ pub const Surface = extern struct {
|
||||
/// to the template so it doesn't have to be unrefed manually.
|
||||
gl_area: *gtk.GLArea,
|
||||
|
||||
/// The apprt Surface.
|
||||
rt_surface: ApprtSurface,
|
||||
|
||||
/// The core surface backing this GTK surface. This starts out
|
||||
/// null because it can't be initialized until there is an available
|
||||
/// GLArea that is realized.
|
||||
//
|
||||
// NOTE(mitchellh): This is a limitation we should definitely remove
|
||||
// at some point by modifying our OpenGL renderer for GTK to
|
||||
// start in an unrealized state. There are other benefits to being
|
||||
// able to initialize the surface early so we should aim for that,
|
||||
// eventually.
|
||||
core_surface: ?*CoreSurface = null,
|
||||
|
||||
pub var offset: c_int = 0;
|
||||
};
|
||||
|
||||
@ -61,11 +80,81 @@ pub const Surface = extern struct {
|
||||
return gobject.ext.newInstance(Self, .{});
|
||||
}
|
||||
|
||||
pub fn core(self: *Self) ?*CoreSurface {
|
||||
const priv = self.private();
|
||||
return priv.core_surface;
|
||||
}
|
||||
|
||||
pub fn rt(self: *Self) *ApprtSurface {
|
||||
const priv = self.private();
|
||||
return &priv.rt_surface;
|
||||
}
|
||||
|
||||
/// Force the surface to redraw itself. Ghostty often will only redraw
|
||||
/// the terminal in reaction to internal changes. If there are external
|
||||
/// events that invalidate the surface, such as the widget moving parents,
|
||||
/// then we should force a redraw.
|
||||
fn redraw(self: *Self) void {
|
||||
const priv = self.private();
|
||||
priv.gl_area.queueRender();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Libghostty Callbacks
|
||||
|
||||
pub fn defaultTermioEnv(self: *Self) !std.process.EnvMap {
|
||||
_ = self;
|
||||
|
||||
const alloc = Application.default().allocator();
|
||||
var env = try internal_os.getEnvMap(alloc);
|
||||
errdefer env.deinit();
|
||||
|
||||
// Don't leak these GTK environment variables to child processes.
|
||||
env.remove("GDK_DEBUG");
|
||||
env.remove("GDK_DISABLE");
|
||||
env.remove("GSK_RENDERER");
|
||||
|
||||
// Remove some environment variables that are set when Ghostty is launched
|
||||
// from a `.desktop` file, by D-Bus activation, or systemd.
|
||||
env.remove("GIO_LAUNCHED_DESKTOP_FILE");
|
||||
env.remove("GIO_LAUNCHED_DESKTOP_FILE_PID");
|
||||
env.remove("DBUS_STARTER_ADDRESS");
|
||||
env.remove("DBUS_STARTER_BUS_TYPE");
|
||||
env.remove("INVOCATION_ID");
|
||||
env.remove("JOURNAL_STREAM");
|
||||
env.remove("NOTIFY_SOCKET");
|
||||
|
||||
// Unset environment varies set by snaps if we're running in a snap.
|
||||
// This allows Ghostty to further launch additional snaps.
|
||||
if (env.get("SNAP")) |_| {
|
||||
env.remove("SNAP");
|
||||
env.remove("DRIRC_CONFIGDIR");
|
||||
env.remove("__EGL_EXTERNAL_PLATFORM_CONFIG_DIRS");
|
||||
env.remove("__EGL_VENDOR_LIBRARY_DIRS");
|
||||
env.remove("LD_LIBRARY_PATH");
|
||||
env.remove("LIBGL_DRIVERS_PATH");
|
||||
env.remove("LIBVA_DRIVERS_PATH");
|
||||
env.remove("VK_LAYER_PATH");
|
||||
env.remove("XLOCALEDIR");
|
||||
env.remove("GDK_PIXBUF_MODULEDIR");
|
||||
env.remove("GDK_PIXBUF_MODULE_FILE");
|
||||
env.remove("GTK_PATH");
|
||||
}
|
||||
|
||||
return env;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Virtual Methods
|
||||
|
||||
fn init(self: *Self, _: *Class) callconv(.C) void {
|
||||
gtk.Widget.initTemplate(self.as(gtk.Widget));
|
||||
|
||||
const priv = self.private();
|
||||
|
||||
// Initialize our apprt surface.
|
||||
priv.rt_surface = .{ .surface = self };
|
||||
|
||||
// If our configuration is null then we get the configuration
|
||||
// from the application.
|
||||
if (priv.config == null) {
|
||||
@ -85,6 +174,20 @@ pub const Surface = extern struct {
|
||||
gl_area.setHasStencilBuffer(0);
|
||||
gl_area.setHasDepthBuffer(0);
|
||||
gl_area.setUseEs(0);
|
||||
_ = gtk.Widget.signals.realize.connect(
|
||||
gl_area,
|
||||
*Self,
|
||||
glareaRealize,
|
||||
self,
|
||||
.{},
|
||||
);
|
||||
_ = gtk.Widget.signals.unrealize.connect(
|
||||
gl_area,
|
||||
*Self,
|
||||
glareaUnrealize,
|
||||
self,
|
||||
.{},
|
||||
);
|
||||
}
|
||||
|
||||
fn dispose(self: *Self) callconv(.C) void {
|
||||
@ -105,24 +208,135 @@ pub const Surface = extern struct {
|
||||
);
|
||||
}
|
||||
|
||||
fn realize(self: *Self) callconv(.C) void {
|
||||
log.debug("realize", .{});
|
||||
fn finalize(self: *Self) callconv(.C) void {
|
||||
const priv = self.private();
|
||||
if (priv.core_surface) |v| {
|
||||
priv.core_surface = null;
|
||||
|
||||
// Call the parent class's realize method.
|
||||
gtk.Widget.virtual_methods.realize.call(
|
||||
// Remove ourselves from the list of known surfaces in the app.
|
||||
// We do this before deinit in case a callback triggers
|
||||
// searching for this surface.
|
||||
Application.default().core().deleteSurface(self.rt());
|
||||
|
||||
// Deinit the surface
|
||||
v.deinit();
|
||||
}
|
||||
|
||||
gobject.Object.virtual_methods.finalize.call(
|
||||
Class.parent,
|
||||
self.as(Parent),
|
||||
);
|
||||
}
|
||||
|
||||
fn unrealize(self: *Self) callconv(.C) void {
|
||||
//---------------------------------------------------------------
|
||||
// Signal Handlers
|
||||
|
||||
fn glareaRealize(
|
||||
_: *gtk.GLArea,
|
||||
self: *Self,
|
||||
) callconv(.c) void {
|
||||
log.debug("realize", .{});
|
||||
|
||||
self.realizeSurface() catch |err| {
|
||||
log.warn("surface failed to realize err={}", .{err});
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
fn glareaUnrealize(
|
||||
gl_area: *gtk.GLArea,
|
||||
self: *Self,
|
||||
) callconv(.c) void {
|
||||
log.debug("unrealize", .{});
|
||||
|
||||
// Call the parent class's unrealize method.
|
||||
gtk.Widget.virtual_methods.unrealize.call(
|
||||
Class.parent,
|
||||
self.as(Parent),
|
||||
// Get our surface. If we don't have one, there's no work we
|
||||
// need to do here.
|
||||
const priv = self.private();
|
||||
const surface = priv.core_surface orelse return;
|
||||
|
||||
// There is no guarantee that our GLArea context is current
|
||||
// when unrealize is emitted, so we need to make it current.
|
||||
gl_area.makeCurrent();
|
||||
if (gl_area.getError()) |err| {
|
||||
// I don't know a scenario this can happen, but it means
|
||||
// we probably leaked memory because displayUnrealized
|
||||
// below frees resources that aren't specifically OpenGL
|
||||
// related. I didn't make the OpenGL renderer handle this
|
||||
// scenario because I don't know if its even possible
|
||||
// under valid circumstances, so let's log.
|
||||
log.warn(
|
||||
"gl_area_make_current failed in unrealize msg={s}",
|
||||
.{err.f_message orelse "(no message)"},
|
||||
);
|
||||
log.warn("OpenGL resources and memory likely leaked", .{});
|
||||
return;
|
||||
}
|
||||
|
||||
surface.renderer.displayUnrealized();
|
||||
}
|
||||
|
||||
const RealizeError = Allocator.Error || error{
|
||||
GLAreaError,
|
||||
RendererError,
|
||||
SurfaceError,
|
||||
};
|
||||
|
||||
fn realizeSurface(self: *Self) RealizeError!void {
|
||||
const priv = self.private();
|
||||
const gl_area = priv.gl_area;
|
||||
|
||||
// We need to make the context current so we can call GL functions.
|
||||
// This is required for all surface operations.
|
||||
gl_area.makeCurrent();
|
||||
if (gl_area.getError()) |err| {
|
||||
log.warn("failed to make GL context current: {s}", .{err.f_message orelse "(no message)"});
|
||||
log.warn("this error is usually due to a driver or gtk bug", .{});
|
||||
log.warn("this is a common cause of this issue: https://gitlab.gnome.org/GNOME/gtk/-/issues/4950", .{});
|
||||
return error.GLAreaError;
|
||||
}
|
||||
|
||||
// If we already have an initialized surface then we just notify.
|
||||
if (priv.core_surface) |v| {
|
||||
v.renderer.displayRealized() catch |err| {
|
||||
log.warn("core displayRealized failed err={}", .{err});
|
||||
return error.RendererError;
|
||||
};
|
||||
self.redraw();
|
||||
return;
|
||||
}
|
||||
|
||||
// Make our pointer to store our surface
|
||||
const app = Application.default();
|
||||
const alloc = app.allocator();
|
||||
const surface = try alloc.create(CoreSurface);
|
||||
errdefer alloc.destroy(surface);
|
||||
|
||||
// Add ourselves to the list of surfaces on the app.
|
||||
try app.core().addSurface(self.rt());
|
||||
errdefer app.core().deleteSurface(self.rt());
|
||||
|
||||
// Initialize our surface configuration.
|
||||
var config = try apprt.surface.newConfig(
|
||||
app.core(),
|
||||
priv.config.?.get(),
|
||||
);
|
||||
defer config.deinit();
|
||||
|
||||
// Initialize the surface
|
||||
surface.init(
|
||||
alloc,
|
||||
&config,
|
||||
app.core(),
|
||||
app.rt(),
|
||||
&priv.rt_surface,
|
||||
) catch |err| {
|
||||
log.warn("failed to initialize surface err={}", .{err});
|
||||
return error.SurfaceError;
|
||||
};
|
||||
errdefer surface.deinit();
|
||||
|
||||
// Store it!
|
||||
priv.core_surface = surface;
|
||||
}
|
||||
|
||||
const C = Common(Self, Private);
|
||||
@ -156,8 +370,7 @@ pub const Surface = extern struct {
|
||||
|
||||
// Virtual methods
|
||||
gobject.Object.virtual_methods.dispose.implement(class, &dispose);
|
||||
gtk.Widget.virtual_methods.realize.implement(class, &realize);
|
||||
gtk.Widget.virtual_methods.unrealize.implement(class, &unrealize);
|
||||
gobject.Object.virtual_methods.finalize.implement(class, &finalize);
|
||||
}
|
||||
|
||||
pub const as = C.Class.as;
|
||||
|
@ -781,6 +781,14 @@ pub fn deinit(self: *Surface) void {
|
||||
self.resize_overlay.deinit();
|
||||
}
|
||||
|
||||
pub fn core(self: *Surface) *CoreSurface {
|
||||
return &self.core_surface;
|
||||
}
|
||||
|
||||
pub fn rtApp(self: *const Surface) *App {
|
||||
return self.app;
|
||||
}
|
||||
|
||||
/// Update our local copy of any configuration that we use.
|
||||
pub fn updateConfig(self: *Surface, config: *const configpkg.Config) !void {
|
||||
self.resize_overlay.updateConfig(config);
|
||||
|
@ -1,3 +1,6 @@
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const apprt = @import("../apprt.zig");
|
||||
const App = @import("../App.zig");
|
||||
const Surface = @import("../Surface.zig");
|
||||
@ -133,7 +136,10 @@ pub const Mailbox = struct {
|
||||
/// Returns a new config for a surface for the given app that should be
|
||||
/// used for any new surfaces. The resulting config should be deinitialized
|
||||
/// after the surface is initialized.
|
||||
pub fn newConfig(app: *const App, config: *const Config) !Config {
|
||||
pub fn newConfig(
|
||||
app: *const App,
|
||||
config: *const Config,
|
||||
) Allocator.Error!Config {
|
||||
// Create a shallow clone
|
||||
var copy = config.shallowClone(app.alloc);
|
||||
|
||||
|
@ -165,7 +165,9 @@ pub fn surfaceInit(surface: *apprt.Surface) !void {
|
||||
else => @compileError("unsupported app runtime for OpenGL"),
|
||||
|
||||
// GTK uses global OpenGL context so we load from null.
|
||||
apprt.gtk => try prepareContext(null),
|
||||
apprt.gtk,
|
||||
apprt.gtk_ng,
|
||||
=> try prepareContext(null),
|
||||
|
||||
apprt.embedded => {
|
||||
// TODO(mitchellh): this does nothing today to allow libghostty
|
||||
@ -199,7 +201,7 @@ pub fn threadEnter(self: *const OpenGL, surface: *apprt.Surface) !void {
|
||||
switch (apprt.runtime) {
|
||||
else => @compileError("unsupported app runtime for OpenGL"),
|
||||
|
||||
apprt.gtk => {
|
||||
apprt.gtk, apprt.gtk_ng => {
|
||||
// GTK doesn't support threaded OpenGL operations as far as I can
|
||||
// tell, so we use the renderer thread to setup all the state
|
||||
// but then do the actual draws and texture syncs and all that
|
||||
@ -221,7 +223,7 @@ pub fn threadExit(self: *const OpenGL) void {
|
||||
switch (apprt.runtime) {
|
||||
else => @compileError("unsupported app runtime for OpenGL"),
|
||||
|
||||
apprt.gtk => {
|
||||
apprt.gtk, apprt.gtk_ng => {
|
||||
// We don't need to do any unloading for GTK because we may
|
||||
// be sharing the global bindings with other windows.
|
||||
},
|
||||
@ -236,7 +238,7 @@ pub fn displayRealized(self: *const OpenGL) void {
|
||||
_ = self;
|
||||
|
||||
switch (apprt.runtime) {
|
||||
apprt.gtk => prepareContext(null) catch |err| {
|
||||
apprt.gtk, apprt.gtk_ng => prepareContext(null) catch |err| {
|
||||
log.warn(
|
||||
"Error preparing GL context in displayRealized, err={}",
|
||||
.{err},
|
||||
|
Reference in New Issue
Block a user