diff --git a/src/apprt/gtk.zig b/src/apprt/gtk.zig index c8d8c5142..258da9970 100644 --- a/src/apprt/gtk.zig +++ b/src/apprt/gtk.zig @@ -30,6 +30,16 @@ pub const App = struct { )) orelse return error.GtkInitFailed; errdefer c.g_object_unref(app); + // Setup our callbacks + _ = c.g_signal_connect_data( + app, + "activate", + c.G_CALLBACK(&activate), + null, + null, + c.G_CONNECT_DEFAULT, + ); + // We don't use g_application_run, we want to manually control the // loop so we have to do the same things the run function does: // https://github.com/GNOME/glib/blob/a8e8b742e7926e33eb635a8edceac74cf239d6ed/gio/gapplication.c#L2533 @@ -51,6 +61,9 @@ pub const App = struct { return error.GtkApplicationRegisterFailed; } + // This just calls the "activate" signal but its part of the normal + // startup routine so we just call it: + // https://gitlab.gnome.org/GNOME/glib/-/blob/bd2ccc2f69ecfd78ca3f34ab59e42e2b462bad65/gio/gapplication.c#L2302 c.g_application_activate(gapp); return .{ .app = app, .ctx = ctx }; @@ -71,6 +84,12 @@ pub const App = struct { pub fn wait(self: App) !void { _ = c.g_main_context_iteration(self.ctx, 1); } + + fn activate(app: *c.GtkApplication, ud: ?*anyopaque) callconv(.C) void { + _ = app; + _ = ud; + log.debug("application activated", .{}); + } }; pub const Window = struct { diff --git a/src/main.zig b/src/main.zig index b880c2116..a29f15057 100644 --- a/src/main.zig +++ b/src/main.zig @@ -101,9 +101,8 @@ pub fn main() !void { // Run our app with a single initial window to start. var app = try App.create(alloc, .{}, &config); defer app.destroy(); - try app.run(); - if (build_config.app_runtime == .gtk) return; _ = try app.newWindow(.{}); + try app.run(); } // Required by tracy/tracy.zig to enable/disable tracy support. diff --git a/src/renderer/OpenGL.zig b/src/renderer/OpenGL.zig index 2f100e7c3..f631ec81e 100644 --- a/src/renderer/OpenGL.zig +++ b/src/renderer/OpenGL.zig @@ -420,34 +420,53 @@ pub fn deinitDevMode(self: *const OpenGL) void { /// Callback called by renderer.Thread when it begins. pub fn threadEnter(self: *const OpenGL, win: apprt.runtime.Window) !void { _ = self; - if (apprt.runtime == apprt.gtk) @panic("TODO"); - // We need to make the OpenGL context current. OpenGL requires - // that a single thread own the a single OpenGL context (if any). This - // ensures that the context switches over to our thread. Important: - // the prior thread MUST have detached the context prior to calling - // this entrypoint. - glfw.makeContextCurrent(win.window); - errdefer glfw.makeContextCurrent(null); - glfw.swapInterval(1); + switch (apprt.runtime) { + else => @compileError("unsupported app runtime for OpenGL"), - // Load OpenGL bindings. This API is context-aware so this sets - // a threadlocal context for these pointers. - const version = try gl.glad.load(&glfw.getProcAddress); - errdefer gl.glad.unload(); - log.info("loaded OpenGL {}.{}", .{ - gl.glad.versionMajor(@intCast(c_uint, version)), - gl.glad.versionMinor(@intCast(c_uint, version)), - }); + apprt.gtk => { + // 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 + // on the main thread. As such, we don't do anything here. + }, + + apprt.glfw => { + // We need to make the OpenGL context current. OpenGL requires + // that a single thread own the a single OpenGL context (if any). This + // ensures that the context switches over to our thread. Important: + // the prior thread MUST have detached the context prior to calling + // this entrypoint. + glfw.makeContextCurrent(win.window); + errdefer glfw.makeContextCurrent(null); + glfw.swapInterval(1); + + // Load OpenGL bindings. This API is context-aware so this sets + // a threadlocal context for these pointers. + const version = try gl.glad.load(&glfw.getProcAddress); + errdefer gl.glad.unload(); + log.info("loaded OpenGL {}.{}", .{ + gl.glad.versionMajor(@intCast(c_uint, version)), + gl.glad.versionMinor(@intCast(c_uint, version)), + }); + }, + } } /// Callback called by renderer.Thread when it exits. pub fn threadExit(self: *const OpenGL) void { _ = self; - if (apprt.runtime == apprt.gtk) @panic("TODO"); - gl.glad.unload(); - glfw.makeContextCurrent(null); + switch (apprt.runtime) { + else => @compileError("unsupported app runtime for OpenGL"), + + apprt.gtk => {}, + + apprt.glfw => { + gl.glad.unload(); + glfw.makeContextCurrent(null); + }, + } } /// Callback when the focus changes for the terminal this is rendering.