mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-14 15:56:13 +03:00
new Window abstraction
This commit is contained in:
76
src/App.zig
76
src/App.zig
@ -5,96 +5,32 @@ const App = @This();
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const glfw = @import("glfw");
|
const Window = @import("Window.zig");
|
||||||
const gl = @import("opengl.zig");
|
|
||||||
const TextRenderer = @import("TextRenderer.zig");
|
|
||||||
const Grid = @import("Grid.zig");
|
|
||||||
|
|
||||||
const log = std.log;
|
const log = std.log;
|
||||||
|
|
||||||
alloc: Allocator,
|
alloc: Allocator,
|
||||||
|
|
||||||
window: glfw.Window,
|
window: *Window,
|
||||||
|
|
||||||
text: TextRenderer,
|
|
||||||
grid: Grid,
|
|
||||||
|
|
||||||
/// Initialize the main app instance. This creates the main window, sets
|
/// Initialize the main app instance. This creates the main window, sets
|
||||||
/// up the renderer state, compiles the shaders, etc. This is the primary
|
/// up the renderer state, compiles the shaders, etc. This is the primary
|
||||||
/// "startup" logic.
|
/// "startup" logic.
|
||||||
pub fn init(alloc: Allocator) !App {
|
pub fn init(alloc: Allocator) !App {
|
||||||
// Create our window
|
// Create the window
|
||||||
const window = try glfw.Window.create(640, 480, "ghostty", null, null, .{
|
const window = try Window.create(alloc);
|
||||||
.context_version_major = 3,
|
|
||||||
.context_version_minor = 3,
|
|
||||||
.opengl_profile = .opengl_core_profile,
|
|
||||||
.opengl_forward_compat = true,
|
|
||||||
});
|
|
||||||
errdefer window.destroy();
|
|
||||||
|
|
||||||
// Setup OpenGL
|
|
||||||
// NOTE(mitchellh): we probably want to extract this to a dedicated
|
|
||||||
// renderer at some point.
|
|
||||||
try glfw.makeContextCurrent(window);
|
|
||||||
try glfw.swapInterval(1);
|
|
||||||
|
|
||||||
// Load OpenGL bindings
|
|
||||||
const version = try gl.glad.load(glfw.getProcAddress);
|
|
||||||
log.info("loaded OpenGL {}.{}", .{
|
|
||||||
gl.glad.versionMajor(version),
|
|
||||||
gl.glad.versionMinor(version),
|
|
||||||
});
|
|
||||||
|
|
||||||
// Culling, probably not necessary. We have to change the winding
|
|
||||||
// order since our 0,0 is top-left.
|
|
||||||
gl.c.glEnable(gl.c.GL_CULL_FACE);
|
|
||||||
gl.c.glFrontFace(gl.c.GL_CW);
|
|
||||||
|
|
||||||
// Blending for text
|
|
||||||
gl.c.glEnable(gl.c.GL_BLEND);
|
|
||||||
gl.c.glBlendFunc(gl.c.GL_SRC_ALPHA, gl.c.GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
|
|
||||||
// Setup our text renderer
|
|
||||||
var texter = try TextRenderer.init(alloc);
|
|
||||||
errdefer texter.deinit(alloc);
|
|
||||||
|
|
||||||
var grid = try Grid.init(alloc);
|
|
||||||
try grid.setScreenSize(.{ .width = 3000, .height = 1666 });
|
|
||||||
|
|
||||||
window.setSizeCallback((struct {
|
|
||||||
fn callback(_: glfw.Window, width: i32, height: i32) void {
|
|
||||||
log.info("set viewport {} {}", .{ width, height });
|
|
||||||
try gl.viewport(0, 0, width, height);
|
|
||||||
}
|
|
||||||
}).callback);
|
|
||||||
|
|
||||||
return App{
|
return App{
|
||||||
.alloc = alloc,
|
.alloc = alloc,
|
||||||
.window = window,
|
.window = window,
|
||||||
.text = texter,
|
|
||||||
.grid = grid,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *App) void {
|
pub fn deinit(self: *App) void {
|
||||||
self.text.deinit(self.alloc);
|
self.window.destroy(self.alloc);
|
||||||
self.window.destroy();
|
|
||||||
self.* = undefined;
|
self.* = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(self: App) !void {
|
pub fn run(self: App) !void {
|
||||||
while (!self.window.shouldClose()) {
|
try self.window.run();
|
||||||
// Setup basic OpenGL settings
|
|
||||||
gl.clearColor(0.2, 0.3, 0.3, 1.0);
|
|
||||||
gl.clear(gl.c.GL_COLOR_BUFFER_BIT);
|
|
||||||
|
|
||||||
try self.grid.render();
|
|
||||||
//try self.text.render("sh $ /bin/bash -c \"echo hello\"", 25.0, 25.0, .{ 0.5, 0.8, 0.2 });
|
|
||||||
|
|
||||||
try self.window.swapBuffers();
|
|
||||||
try glfw.waitEvents();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const vs_source = @embedFile("../shaders/shape.v.glsl");
|
|
||||||
const fs_source = @embedFile("../shaders/shape.f.glsl");
|
|
||||||
|
109
src/Window.zig
Normal file
109
src/Window.zig
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
//! Window represents a single OS window.
|
||||||
|
//!
|
||||||
|
//! NOTE(multi-window): This may be premature, but this abstraction is here
|
||||||
|
//! to pave the way One Day(tm) for multi-window support. At the time of
|
||||||
|
//! writing, we support exactly one window.
|
||||||
|
const Window = @This();
|
||||||
|
|
||||||
|
const std = @import("std");
|
||||||
|
const Allocator = std.mem.Allocator;
|
||||||
|
const Grid = @import("Grid.zig");
|
||||||
|
const glfw = @import("glfw");
|
||||||
|
const gl = @import("opengl.zig");
|
||||||
|
|
||||||
|
const log = std.log.scoped(.window);
|
||||||
|
|
||||||
|
/// The glfw window handle.
|
||||||
|
window: glfw.Window,
|
||||||
|
|
||||||
|
/// The terminal grid attached to this window.
|
||||||
|
grid: Grid,
|
||||||
|
|
||||||
|
/// Create a new window. This allocates and returns a pointer because we
|
||||||
|
/// need a stable pointer for user data callbacks. Therefore, a stack-only
|
||||||
|
/// initialization is not currently possible.
|
||||||
|
pub fn create(alloc: Allocator) !*Window {
|
||||||
|
var self = try alloc.create(Window);
|
||||||
|
errdefer alloc.destroy(self);
|
||||||
|
|
||||||
|
// Create our window
|
||||||
|
const window = try glfw.Window.create(640, 480, "ghostty", null, null, .{
|
||||||
|
.context_version_major = 3,
|
||||||
|
.context_version_minor = 3,
|
||||||
|
.opengl_profile = .opengl_core_profile,
|
||||||
|
.opengl_forward_compat = true,
|
||||||
|
});
|
||||||
|
errdefer window.destroy();
|
||||||
|
|
||||||
|
// NOTE(multi-window): We'll need to extract all the below into a
|
||||||
|
// dedicated renderer and consider the multi-threading (or at the very
|
||||||
|
// least: multi-OpenGL-context) implications. Since we don't support
|
||||||
|
// multiple windows right now, we just do it all here.
|
||||||
|
|
||||||
|
// Setup OpenGL
|
||||||
|
try glfw.makeContextCurrent(window);
|
||||||
|
try glfw.swapInterval(1);
|
||||||
|
|
||||||
|
// Load OpenGL bindings
|
||||||
|
const version = try gl.glad.load(glfw.getProcAddress);
|
||||||
|
log.info("loaded OpenGL {}.{}", .{
|
||||||
|
gl.glad.versionMajor(version),
|
||||||
|
gl.glad.versionMinor(version),
|
||||||
|
});
|
||||||
|
|
||||||
|
// Culling, probably not necessary. We have to change the winding
|
||||||
|
// order since our 0,0 is top-left.
|
||||||
|
gl.c.glEnable(gl.c.GL_CULL_FACE);
|
||||||
|
gl.c.glFrontFace(gl.c.GL_CW);
|
||||||
|
|
||||||
|
// Blending for text
|
||||||
|
gl.c.glEnable(gl.c.GL_BLEND);
|
||||||
|
gl.c.glBlendFunc(gl.c.GL_SRC_ALPHA, gl.c.GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
// Create our terminal grid with a bogus initial size.
|
||||||
|
var grid = try Grid.init(alloc);
|
||||||
|
try grid.setScreenSize(.{ .width = 640, .height = 480 });
|
||||||
|
|
||||||
|
self.* = .{
|
||||||
|
.window = window,
|
||||||
|
.grid = grid,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Setup our callbacks and user data
|
||||||
|
window.setUserPointer(self);
|
||||||
|
window.setSizeCallback(sizeCallback);
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn destroy(self: *Window, alloc: Allocator) void {
|
||||||
|
alloc.destroy(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run(self: Window) !void {
|
||||||
|
while (!self.window.shouldClose()) {
|
||||||
|
// Set our background
|
||||||
|
gl.clearColor(0.2, 0.3, 0.3, 1.0);
|
||||||
|
gl.clear(gl.c.GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
// Render the grid
|
||||||
|
try self.grid.render();
|
||||||
|
|
||||||
|
// Swap
|
||||||
|
try self.window.swapBuffers();
|
||||||
|
try glfw.waitEvents();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sizeCallback(window: glfw.Window, width: i32, height: i32) void {
|
||||||
|
const win = window.getUserPointer(Window) orelse return;
|
||||||
|
|
||||||
|
// Update our grid so that the projections on render are correct.
|
||||||
|
win.grid.setScreenSize(.{
|
||||||
|
.width = width,
|
||||||
|
.height = height,
|
||||||
|
}) catch unreachable;
|
||||||
|
|
||||||
|
// Update our viewport for this context to be the entire window
|
||||||
|
try gl.viewport(0, 0, width, height);
|
||||||
|
}
|
@ -8,7 +8,7 @@ pub fn main() !void {
|
|||||||
const gpa = general_purpose_allocator.allocator();
|
const gpa = general_purpose_allocator.allocator();
|
||||||
defer _ = general_purpose_allocator.deinit();
|
defer _ = general_purpose_allocator.deinit();
|
||||||
|
|
||||||
// List our fonts
|
// Initialize glfw
|
||||||
try glfw.init(.{});
|
try glfw.init(.{});
|
||||||
defer glfw.terminate();
|
defer glfw.terminate();
|
||||||
|
|
||||||
|
52
src/old/App.zig
Normal file
52
src/old/App.zig
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
//! App is the primary GUI application for ghostty. This builds the window,
|
||||||
|
//! sets up the renderer, etc. The primary run loop is started by calling
|
||||||
|
//! the "run" function.
|
||||||
|
const App = @This();
|
||||||
|
|
||||||
|
const std = @import("std");
|
||||||
|
const Allocator = std.mem.Allocator;
|
||||||
|
const glfw = @import("glfw");
|
||||||
|
const gl = @import("opengl.zig");
|
||||||
|
const TextRenderer = @import("TextRenderer.zig");
|
||||||
|
const Grid = @import("Grid.zig");
|
||||||
|
const Window = @import("Window.zig");
|
||||||
|
|
||||||
|
const log = std.log;
|
||||||
|
|
||||||
|
alloc: Allocator,
|
||||||
|
|
||||||
|
window: glfw.Window,
|
||||||
|
|
||||||
|
text: TextRenderer,
|
||||||
|
grid: Grid,
|
||||||
|
|
||||||
|
/// Initialize the main app instance. This creates the main window, sets
|
||||||
|
/// up the renderer state, compiles the shaders, etc. This is the primary
|
||||||
|
/// "startup" logic.
|
||||||
|
pub fn init(alloc: Allocator) !App {
|
||||||
|
// Create the window
|
||||||
|
const window = try Window.create(alloc);
|
||||||
|
|
||||||
|
return App{
|
||||||
|
.window = window,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *App) void {
|
||||||
|
self.window.destroy();
|
||||||
|
self.* = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run(self: App) !void {
|
||||||
|
while (!self.window.shouldClose()) {
|
||||||
|
// Setup basic OpenGL settings
|
||||||
|
gl.clearColor(0.2, 0.3, 0.3, 1.0);
|
||||||
|
gl.clear(gl.c.GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
try self.grid.render();
|
||||||
|
//try self.text.render("sh $ /bin/bash -c \"echo hello\"", 25.0, 25.0, .{ 0.5, 0.8, 0.2 });
|
||||||
|
|
||||||
|
try self.window.swapBuffers();
|
||||||
|
try glfw.waitEvents();
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user