mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
init gtk app
This commit is contained in:
@ -22,6 +22,7 @@
|
|||||||
, expat
|
, expat
|
||||||
, fontconfig
|
, fontconfig
|
||||||
, freetype
|
, freetype
|
||||||
|
, glib
|
||||||
, gtk4
|
, gtk4
|
||||||
, harfbuzz
|
, harfbuzz
|
||||||
, libpng
|
, libpng
|
||||||
@ -56,6 +57,7 @@ let
|
|||||||
libXrandr
|
libXrandr
|
||||||
|
|
||||||
gtk4
|
gtk4
|
||||||
|
glib
|
||||||
];
|
];
|
||||||
in mkShell rec {
|
in mkShell rec {
|
||||||
name = "ghostty";
|
name = "ghostty";
|
||||||
@ -108,6 +110,7 @@ in mkShell rec {
|
|||||||
|
|
||||||
# Only needed for GTK builds
|
# Only needed for GTK builds
|
||||||
gtk4
|
gtk4
|
||||||
|
glib
|
||||||
];
|
];
|
||||||
|
|
||||||
# This should be set onto the rpath of the ghostty binary if you want
|
# This should be set onto the rpath of the ghostty binary if you want
|
||||||
|
@ -125,10 +125,11 @@ pub fn destroy(self: *App) void {
|
|||||||
self.windows.deinit(self.alloc);
|
self.windows.deinit(self.alloc);
|
||||||
if (Darwin.enabled) self.darwin.deinit();
|
if (Darwin.enabled) self.darwin.deinit();
|
||||||
self.mailbox.destroy(self.alloc);
|
self.mailbox.destroy(self.alloc);
|
||||||
self.alloc.destroy(self);
|
|
||||||
|
|
||||||
// Close our windowing runtime
|
// Close our windowing runtime
|
||||||
self.runtime.terminate();
|
self.runtime.terminate();
|
||||||
|
|
||||||
|
self.alloc.destroy(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wake up the app event loop. This should be called after any messages
|
/// Wake up the app event loop. This should be called after any messages
|
||||||
@ -164,7 +165,7 @@ pub fn tick(self: *App) !void {
|
|||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drain our mailbox only if we're not quitting.
|
// // Drain our mailbox only if we're not quitting.
|
||||||
if (!self.quit) try self.drainMailbox();
|
if (!self.quit) try self.drainMailbox();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,9 @@ const std = @import("std");
|
|||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
|
const apprt = @import("../apprt.zig");
|
||||||
|
const CoreApp = @import("../App.zig");
|
||||||
|
const CoreWindow = @import("../Window.zig");
|
||||||
|
|
||||||
pub const c = @cImport({
|
pub const c = @cImport({
|
||||||
@cInclude("gtk/gtk.h");
|
@cInclude("gtk/gtk.h");
|
||||||
@ -17,29 +20,111 @@ pub const App = struct {
|
|||||||
id: [:0]const u8 = "com.mitchellh.ghostty",
|
id: [:0]const u8 = "com.mitchellh.ghostty",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
app: *c.GtkApplication,
|
||||||
|
ctx: *c.GMainContext,
|
||||||
|
|
||||||
pub fn init(opts: Options) !App {
|
pub fn init(opts: Options) !App {
|
||||||
const app = c.gtk_application_new(opts.id.ptr, c.G_APPLICATION_DEFAULT_FLAGS);
|
const app = @ptrCast(?*c.GtkApplication, c.gtk_application_new(
|
||||||
|
opts.id.ptr,
|
||||||
|
c.G_APPLICATION_DEFAULT_FLAGS,
|
||||||
|
)) orelse return error.GtkInitFailed;
|
||||||
errdefer c.g_object_unref(app);
|
errdefer c.g_object_unref(app);
|
||||||
return .{};
|
|
||||||
|
// 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
|
||||||
|
const ctx = c.g_main_context_default() orelse return error.GtkContextFailed;
|
||||||
|
if (c.g_main_context_acquire(ctx) == 0) return error.GtkContextAcquireFailed;
|
||||||
|
errdefer c.g_main_context_release(ctx);
|
||||||
|
|
||||||
|
const gapp = @ptrCast(*c.GApplication, app);
|
||||||
|
var err_: ?*c.GError = null;
|
||||||
|
if (c.g_application_register(
|
||||||
|
gapp,
|
||||||
|
null,
|
||||||
|
@ptrCast([*c][*c]c.GError, &err_),
|
||||||
|
) == 0) {
|
||||||
|
if (err_) |err| {
|
||||||
|
log.warn("error registering application: {s}", .{err.message});
|
||||||
|
c.g_error_free(err);
|
||||||
|
}
|
||||||
|
return error.GtkApplicationRegisterFailed;
|
||||||
|
}
|
||||||
|
|
||||||
|
c.g_application_activate(gapp);
|
||||||
|
|
||||||
|
return .{ .app = app, .ctx = ctx };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn terminate(self: App) void {
|
pub fn terminate(self: App) void {
|
||||||
_ = self;
|
c.g_settings_sync();
|
||||||
|
while (c.g_main_context_iteration(self.ctx, 0) != 0) {}
|
||||||
|
c.g_main_context_release(self.ctx);
|
||||||
|
c.g_object_unref(self.app);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn wakeup(self: App) !void {
|
pub fn wakeup(self: App) !void {
|
||||||
_ = self;
|
_ = self;
|
||||||
|
c.g_main_context_wakeup(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn wait(self: App) !void {
|
pub fn wait(self: App) !void {
|
||||||
_ = self;
|
_ = c.g_main_context_iteration(self.ctx, 1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Window = struct {
|
pub const Window = struct {
|
||||||
pub const Options = struct {};
|
pub const Options = struct {};
|
||||||
|
|
||||||
|
pub fn init(app: *const CoreApp, core_win: *CoreWindow, opts: Options) !Window {
|
||||||
|
_ = app;
|
||||||
|
_ = core_win;
|
||||||
|
_ = opts;
|
||||||
|
|
||||||
|
return .{};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *Window) void {
|
pub fn deinit(self: *Window) void {
|
||||||
_ = self;
|
_ = self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn setShouldClose(self: *Window) void {
|
||||||
|
_ = self;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn shouldClose(self: *const Window) bool {
|
||||||
|
_ = self;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getContentScale(self: *const Window) !apprt.ContentScale {
|
||||||
|
_ = self;
|
||||||
|
return .{ .x = 1, .y = 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getSize(self: *const Window) !apprt.WindowSize {
|
||||||
|
_ = self;
|
||||||
|
return .{ .width = 800, .height = 600 };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setSizeLimits(self: *Window, min: apprt.WindowSize, max_: ?apprt.WindowSize) !void {
|
||||||
|
_ = self;
|
||||||
|
_ = min;
|
||||||
|
_ = max_;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setTitle(self: *Window, slice: [:0]const u8) !void {
|
||||||
|
_ = self;
|
||||||
|
_ = slice;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getClipboardString(self: *const Window) ![:0]const u8 {
|
||||||
|
_ = self;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setClipboardString(self: *const Window, val: [:0]const u8) !void {
|
||||||
|
_ = self;
|
||||||
|
_ = val;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
@ -101,9 +101,9 @@ pub fn main() !void {
|
|||||||
// Run our app with a single initial window to start.
|
// Run our app with a single initial window to start.
|
||||||
var app = try App.create(alloc, .{}, &config);
|
var app = try App.create(alloc, .{}, &config);
|
||||||
defer app.destroy();
|
defer app.destroy();
|
||||||
|
try app.run();
|
||||||
if (build_config.app_runtime == .gtk) return;
|
if (build_config.app_runtime == .gtk) return;
|
||||||
_ = try app.newWindow(.{});
|
_ = try app.newWindow(.{});
|
||||||
try app.run();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Required by tracy/tracy.zig to enable/disable tracy support.
|
// Required by tracy/tracy.zig to enable/disable tracy support.
|
||||||
|
@ -444,6 +444,7 @@ pub fn threadEnter(self: *const OpenGL, win: apprt.runtime.Window) !void {
|
|||||||
/// Callback called by renderer.Thread when it exits.
|
/// Callback called by renderer.Thread when it exits.
|
||||||
pub fn threadExit(self: *const OpenGL) void {
|
pub fn threadExit(self: *const OpenGL) void {
|
||||||
_ = self;
|
_ = self;
|
||||||
|
if (apprt.runtime == apprt.gtk) @panic("TODO");
|
||||||
|
|
||||||
gl.glad.unload();
|
gl.glad.unload();
|
||||||
glfw.makeContextCurrent(null);
|
glfw.makeContextCurrent(null);
|
||||||
@ -569,12 +570,14 @@ pub fn render(
|
|||||||
|
|
||||||
// Build our devmode draw data
|
// Build our devmode draw data
|
||||||
const devmode_data = devmode_data: {
|
const devmode_data = devmode_data: {
|
||||||
if (state.devmode) |dm| {
|
if (DevMode.enabled) {
|
||||||
if (dm.visible) {
|
if (state.devmode) |dm| {
|
||||||
imgui.ImplOpenGL3.newFrame();
|
if (dm.visible) {
|
||||||
imgui.ImplGlfw.newFrame();
|
imgui.ImplOpenGL3.newFrame();
|
||||||
try dm.update();
|
imgui.ImplGlfw.newFrame();
|
||||||
break :devmode_data try dm.render();
|
try dm.update();
|
||||||
|
break :devmode_data try dm.render();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -639,11 +642,14 @@ pub fn render(
|
|||||||
try self.draw();
|
try self.draw();
|
||||||
|
|
||||||
// If we have devmode, then render that
|
// If we have devmode, then render that
|
||||||
if (critical.devmode_data) |data| {
|
if (DevMode.enabled) {
|
||||||
imgui.ImplOpenGL3.renderDrawData(data);
|
if (critical.devmode_data) |data| {
|
||||||
|
imgui.ImplOpenGL3.renderDrawData(data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Swap our window buffers
|
// Swap our window buffers
|
||||||
|
if (apprt.runtime == apprt.gtk) @panic("TODO");
|
||||||
win.window.swapBuffers();
|
win.window.swapBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user