mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-14 15:56:13 +03:00
move config loading into apprt to prep for reloading
This commit is contained in:
35
src/App.zig
35
src/App.zig
@ -30,11 +30,6 @@ alloc: Allocator,
|
||||
/// The list of surfaces that are currently active.
|
||||
surfaces: SurfaceList,
|
||||
|
||||
// The configuration for the app. This may change (app runtimes are notified
|
||||
// via the callback), but the change will only ever happen during tick()
|
||||
// so app runtimes can ensure there are no data races in reading this.
|
||||
config: *const Config,
|
||||
|
||||
/// The mailbox that can be used to send this thread messages. Note
|
||||
/// this is a blocking queue so if it is full you will get errors (or block).
|
||||
mailbox: Mailbox.Queue,
|
||||
@ -47,17 +42,15 @@ quit: bool,
|
||||
/// "startup" logic.
|
||||
pub fn create(
|
||||
alloc: Allocator,
|
||||
config: *const Config,
|
||||
) !*App {
|
||||
// If we have DevMode on, store the config so we can show it
|
||||
if (DevMode.enabled) DevMode.instance.config = config;
|
||||
//if (DevMode.enabled) DevMode.instance.config = config;
|
||||
|
||||
var app = try alloc.create(App);
|
||||
errdefer alloc.destroy(app);
|
||||
app.* = .{
|
||||
.alloc = alloc,
|
||||
.surfaces = .{},
|
||||
.config = config,
|
||||
.mailbox = .{},
|
||||
.quit = false,
|
||||
};
|
||||
@ -99,6 +92,21 @@ pub fn tick(self: *App, rt_app: *apprt.App) !bool {
|
||||
return self.quit or self.surfaces.items.len == 0;
|
||||
}
|
||||
|
||||
/// Update the configuration associated with the app. This can only be
|
||||
/// called from the main thread.
|
||||
///
|
||||
/// The caller owns the config memory. The prior config must not be freed
|
||||
/// until this function returns successfully.
|
||||
pub fn updateConfig(self: *App, config: *const Config) !void {
|
||||
// Update our config
|
||||
self.config = config;
|
||||
|
||||
// Go through and update all of the surface configurations.
|
||||
for (self.surfaces.items) |surface| {
|
||||
try surface.handleMessage(.{ .change_config = config });
|
||||
}
|
||||
}
|
||||
|
||||
/// Add an initialized surface. This is really only for the runtime
|
||||
/// implementations to call and should NOT be called by general app users.
|
||||
/// The surface must be from the pool.
|
||||
@ -125,6 +133,7 @@ fn drainMailbox(self: *App, rt_app: *apprt.App) !void {
|
||||
while (self.mailbox.pop()) |message| {
|
||||
log.debug("mailbox message={s}", .{@tagName(message)});
|
||||
switch (message) {
|
||||
.reload_config => try self.reloadConfig(rt_app),
|
||||
.new_window => |msg| try self.newWindow(rt_app, msg),
|
||||
.close => |surface| try self.closeSurface(rt_app, surface),
|
||||
.quit => try self.setQuit(),
|
||||
@ -134,6 +143,12 @@ fn drainMailbox(self: *App, rt_app: *apprt.App) !void {
|
||||
}
|
||||
}
|
||||
|
||||
fn reloadConfig(self: *App, rt_app: *apprt.App) !void {
|
||||
_ = rt_app;
|
||||
_ = self;
|
||||
//try rt_app.reloadConfig();
|
||||
}
|
||||
|
||||
fn closeSurface(self: *App, rt_app: *apprt.App, surface: *Surface) !void {
|
||||
if (!self.hasSurface(surface)) return;
|
||||
rt_app.closeSurface(surface.rt_surface);
|
||||
@ -195,6 +210,10 @@ fn hasSurface(self: *App, surface: *Surface) bool {
|
||||
|
||||
/// The message types that can be sent to the app thread.
|
||||
pub const Message = union(enum) {
|
||||
/// Reload the configuration for the entire app and propagate it to
|
||||
/// all the active surfaces.
|
||||
reload_config: void,
|
||||
|
||||
/// Create a new terminal window.
|
||||
new_window: NewWindow,
|
||||
|
||||
|
@ -528,6 +528,8 @@ pub fn close(self: *Surface) void {
|
||||
/// surface.
|
||||
pub fn handleMessage(self: *Surface, msg: Message) !void {
|
||||
switch (msg) {
|
||||
.change_config => |config| try self.changeConfig(config),
|
||||
|
||||
.set_title => |*v| {
|
||||
// The ptrCast just gets sliceTo to return the proper type.
|
||||
// We know that our title should end in 0.
|
||||
@ -553,6 +555,24 @@ pub fn handleMessage(self: *Surface, msg: Message) !void {
|
||||
}
|
||||
}
|
||||
|
||||
/// Update our configuration at runtime.
|
||||
fn changeConfig(self: *Surface, config: *const configpkg.Config) !void {
|
||||
// Update our new derived config immediately
|
||||
const derived = DerivedConfig.init(self.alloc, config) catch |err| {
|
||||
// If the derivation fails then we just log and return. We don't
|
||||
// hard fail in this case because we don't want to error the surface
|
||||
// when config fails we just want to keep using the old config.
|
||||
log.err("error updating configuration err={}", .{err});
|
||||
return;
|
||||
};
|
||||
self.config.deinit();
|
||||
self.config = derived;
|
||||
|
||||
// Update our derived configurations for the renderer and termio,
|
||||
// then send them a message to update.
|
||||
// TODO
|
||||
}
|
||||
|
||||
/// Returns the x/y coordinate of where the IME (Input Method Editor)
|
||||
/// keyboard should be rendered.
|
||||
pub fn imePoint(self: *const Surface) apprt.IMEPos {
|
||||
|
@ -19,6 +19,7 @@ const Renderer = renderer.Renderer;
|
||||
const apprt = @import("../apprt.zig");
|
||||
const CoreApp = @import("../App.zig");
|
||||
const CoreSurface = @import("../Surface.zig");
|
||||
const Config = @import("../config.zig").Config;
|
||||
|
||||
// Get native API access on certain platforms so we can do more customization.
|
||||
const glfwNative = glfw.Native(.{
|
||||
@ -29,6 +30,7 @@ const log = std.log.scoped(.glfw);
|
||||
|
||||
pub const App = struct {
|
||||
app: *CoreApp,
|
||||
config: Config,
|
||||
|
||||
/// Mac-specific state.
|
||||
darwin: if (Darwin.enabled) Darwin else void,
|
||||
@ -53,14 +55,19 @@ pub const App = struct {
|
||||
var darwin = if (Darwin.enabled) try Darwin.init() else {};
|
||||
errdefer if (Darwin.enabled) darwin.deinit();
|
||||
|
||||
// Load our configuration
|
||||
var config = try Config.load(core_app.alloc);
|
||||
errdefer config.deinit();
|
||||
|
||||
return .{
|
||||
.app = core_app,
|
||||
.config = config,
|
||||
.darwin = darwin,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn terminate(self: App) void {
|
||||
_ = self;
|
||||
pub fn terminate(self: *App) void {
|
||||
self.config.deinit();
|
||||
glfw.terminate();
|
||||
}
|
||||
|
||||
@ -139,7 +146,7 @@ pub const App = struct {
|
||||
errdefer surface.deinit();
|
||||
|
||||
// If we have a parent, inherit some properties
|
||||
if (self.app.config.@"window-inherit-font-size") {
|
||||
if (self.config.@"window-inherit-font-size") {
|
||||
if (parent_) |parent| {
|
||||
surface.core_surface.setFontSize(parent.font_size);
|
||||
}
|
||||
@ -313,7 +320,7 @@ pub const Surface = struct {
|
||||
// Initialize our surface now that we have the stable pointer.
|
||||
try self.core_surface.init(
|
||||
app.app.alloc,
|
||||
app.app.config,
|
||||
&app.config,
|
||||
.{ .rt_app = app, .mailbox = &app.app.mailbox },
|
||||
self,
|
||||
);
|
||||
|
@ -9,6 +9,7 @@ const apprt = @import("../apprt.zig");
|
||||
const input = @import("../input.zig");
|
||||
const CoreApp = @import("../App.zig");
|
||||
const CoreSurface = @import("../Surface.zig");
|
||||
const Config = @import("../config.zig").Config;
|
||||
|
||||
pub const c = @cImport({
|
||||
@cInclude("gtk/gtk.h");
|
||||
@ -37,6 +38,7 @@ pub const App = struct {
|
||||
};
|
||||
|
||||
core_app: *CoreApp,
|
||||
config: Config,
|
||||
|
||||
app: *c.GtkApplication,
|
||||
ctx: *c.GMainContext,
|
||||
@ -53,6 +55,10 @@ pub const App = struct {
|
||||
// rid of this dep.
|
||||
if (!glfw.init(.{})) return error.GlfwInitFailed;
|
||||
|
||||
// Load our configuration
|
||||
var config = try Config.load(core_app.alloc);
|
||||
errdefer config.deinit();
|
||||
|
||||
// Create our GTK Application which encapsulates our process.
|
||||
const app = @ptrCast(?*c.GtkApplication, c.gtk_application_new(
|
||||
null,
|
||||
@ -108,6 +114,7 @@ pub const App = struct {
|
||||
return .{
|
||||
.core_app = core_app,
|
||||
.app = app,
|
||||
.config = config,
|
||||
.ctx = ctx,
|
||||
.cursor_default = cursor_default,
|
||||
.cursor_ibeam = cursor_ibeam,
|
||||
@ -116,7 +123,7 @@ pub const App = struct {
|
||||
|
||||
// Terminate the application. The application will not be restarted after
|
||||
// this so all global state can be cleaned up.
|
||||
pub fn terminate(self: App) void {
|
||||
pub fn terminate(self: *App) void {
|
||||
c.g_settings_sync();
|
||||
while (c.g_main_context_iteration(self.ctx, 0) != 0) {}
|
||||
c.g_main_context_release(self.ctx);
|
||||
@ -125,6 +132,8 @@ pub const App = struct {
|
||||
c.g_object_unref(self.cursor_ibeam);
|
||||
c.g_object_unref(self.cursor_default);
|
||||
|
||||
self.config.deinit();
|
||||
|
||||
glfw.terminate();
|
||||
}
|
||||
|
||||
@ -575,7 +584,7 @@ pub const Surface = struct {
|
||||
// Initialize our surface now that we have the stable pointer.
|
||||
try self.core_surface.init(
|
||||
self.app.core_app.alloc,
|
||||
self.app.core_app.config,
|
||||
&self.app.config,
|
||||
.{ .rt_app = self.app, .mailbox = &self.app.core_app.mailbox },
|
||||
self,
|
||||
);
|
||||
|
@ -2,6 +2,7 @@ const App = @import("../App.zig");
|
||||
const Surface = @import("../Surface.zig");
|
||||
const renderer = @import("../renderer.zig");
|
||||
const termio = @import("../termio.zig");
|
||||
const Config = @import("../config.zig").Config;
|
||||
|
||||
/// The message types that can be sent to a single surface.
|
||||
pub const Message = union(enum) {
|
||||
@ -24,6 +25,11 @@ pub const Message = union(enum) {
|
||||
/// Write the clipboard contents.
|
||||
clipboard_write: WriteReq,
|
||||
|
||||
/// Change the configuration to the given configuration. The pointer is
|
||||
/// not valid after receiving this message so any config must be used
|
||||
/// and derived immediately.
|
||||
change_config: *const Config,
|
||||
|
||||
/// Close the surface. This will only close the current surface that
|
||||
/// receives this, not the full application.
|
||||
close: void,
|
||||
|
@ -14,8 +14,6 @@ const xdg = @import("xdg.zig");
|
||||
const apprt = @import("apprt.zig");
|
||||
|
||||
const App = @import("App.zig");
|
||||
const cli_args = @import("cli_args.zig");
|
||||
const Config = @import("config.zig").Config;
|
||||
const Ghostty = @import("main_c.zig").Ghostty;
|
||||
|
||||
/// Global process state. This is initialized in main() for exe artifacts
|
||||
@ -29,13 +27,8 @@ pub fn main() !void {
|
||||
defer state.deinit();
|
||||
const alloc = state.alloc;
|
||||
|
||||
// Try reading our config
|
||||
var config = try Config.load(alloc);
|
||||
defer config.deinit();
|
||||
//std.log.debug("config={}", .{config});
|
||||
|
||||
// Create our app state
|
||||
var app = try App.create(alloc, &config);
|
||||
var app = try App.create(alloc);
|
||||
defer app.destroy();
|
||||
|
||||
// Create our runtime app
|
||||
|
Reference in New Issue
Block a user