Files
playpen/src/main.zig
T
2026-08-11 14:26:12 -04:00

74 lines
2.5 KiB
Zig

//! Playpen: a terminal with vertical tabs, web panes and saved layouts, built
//! on libghostty-vt.
//!
//! libghostty-vt supplies the terminal emulator core (escape sequence
//! parsing, screen and scrollback state, key/mouse encoding). Everything
//! else — process management, rendering, and the GTK4 UI — lives here.
const std = @import("std");
const adw = @import("adw");
const gdk = @import("gdk");
const gio = @import("gio");
const gtk = @import("gtk");
const Window = @import("Window.zig");
/// libghostty-vt logs unimplemented sequences at debug level, which is very
/// chatty against a real shell. Keep the app's own warnings and errors.
pub const std_options: std.Options = .{
.log_level = .info,
};
const css = @embedFile("style.css");
var gpa: std.heap.DebugAllocator(.{}) = .init;
pub fn main() u8 {
defer _ = gpa.deinit();
// Non-unique so every launch is its own process. The default GApplication
// behavior hands off to an already-running instance over D-Bus, which for
// a terminal means a second launch silently does nothing visible here and
// opens a window in whatever session owns the first one.
const app = adw.Application.new("dev.greyson.playpen", .{ .non_unique = true });
defer app.unref();
_ = gio.Application.signals.activate.connect(app, ?*anyopaque, &onActivate, null, .{});
const status = gio.Application.run(app.as(gio.Application), 0, null);
return @intCast(status);
}
fn onActivate(app: *adw.Application, _: ?*anyopaque) callconv(.c) void {
forceDark();
loadCss();
const window = Window.create(gpa.allocator(), app) catch |err| {
std.log.err("failed to create window: {s}", .{@errorName(err)});
return;
};
window.present();
}
/// The window's own chrome is dark by hand in `style.css`, but stock widgets —
/// popovers, dialogs, text entries — follow the desktop's colour scheme and
/// would come up light against it. Layouts brought the first real dialogs into
/// the app, which is where that mismatch became visible.
fn forceDark() void {
const manager = adw.StyleManager.getDefault();
manager.setColorScheme(.force_dark);
}
fn loadCss() void {
const display = gdk.Display.getDefault() orelse return;
const provider = gtk.CssProvider.new();
defer provider.unref();
provider.loadFromString(css);
gtk.StyleContext.addProviderForDisplay(
display,
provider.as(gtk.StyleProvider),
gtk.STYLE_PROVIDER_PRIORITY_APPLICATION,
);
}