mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-23 20:26:09 +03:00
App prepare for multi-window
This commit is contained in:
85
src/App.zig
85
src/App.zig
@ -9,46 +9,111 @@ const glfw = @import("glfw");
|
||||
const Window = @import("Window.zig");
|
||||
const tracy = @import("tracy");
|
||||
const Config = @import("config.zig").Config;
|
||||
const BlockingQueue = @import("./blocking_queue.zig").BlockingQueue;
|
||||
|
||||
const log = std.log.scoped(.app);
|
||||
|
||||
const WindowList = std.ArrayListUnmanaged(*Window);
|
||||
|
||||
/// The type used for sending messages to the app thread.
|
||||
pub const Mailbox = BlockingQueue(Message, 64);
|
||||
|
||||
/// General purpose allocator
|
||||
alloc: Allocator,
|
||||
|
||||
/// The primary window for the application. We currently support only
|
||||
/// single window operations.
|
||||
window: *Window,
|
||||
/// The list of windows that are currently open
|
||||
windows: WindowList,
|
||||
|
||||
// The configuration for the app.
|
||||
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,
|
||||
|
||||
/// 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, config: *const Config) !App {
|
||||
// Create the window
|
||||
// The mailbox for messaging this thread
|
||||
var mailbox = try Mailbox.create(alloc);
|
||||
errdefer mailbox.destroy(alloc);
|
||||
|
||||
// Create the first window
|
||||
var window = try Window.create(alloc, config);
|
||||
errdefer window.destroy();
|
||||
|
||||
// Create our windows list and add our initial window.
|
||||
var windows: WindowList = .{};
|
||||
errdefer windows.deinit(alloc);
|
||||
try windows.append(alloc, window);
|
||||
|
||||
return App{
|
||||
.alloc = alloc,
|
||||
.window = window,
|
||||
.windows = windows,
|
||||
.config = config,
|
||||
.mailbox = mailbox,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: *App) void {
|
||||
self.window.destroy();
|
||||
// Clean up all our windows
|
||||
for (self.windows.items) |window| window.destroy();
|
||||
self.windows.deinit(self.alloc);
|
||||
self.mailbox.destroy(self.alloc);
|
||||
self.* = undefined;
|
||||
}
|
||||
|
||||
pub fn run(self: App) !void {
|
||||
while (!self.window.shouldClose()) {
|
||||
// Block for any glfw events. This may also be an "empty" event
|
||||
// posted by the libuv watcher so that we trigger a libuv loop tick.
|
||||
/// Wake up the app event loop. This should be called after any messages
|
||||
/// are sent to the mailbox.
|
||||
pub fn wakeup(self: App) void {
|
||||
_ = self;
|
||||
glfw.postEmptyEvent() catch {};
|
||||
}
|
||||
|
||||
/// Run the main event loop for the application. This blocks until the
|
||||
/// application quits or every window is closed.
|
||||
pub fn run(self: *App) !void {
|
||||
while (self.windows.items.len > 0) {
|
||||
// Block for any glfw events.
|
||||
try glfw.waitEvents();
|
||||
|
||||
// Mark this so we're in a totally different "frame"
|
||||
tracy.frameMark();
|
||||
|
||||
// If any windows are closing, destroy them
|
||||
var i: usize = 0;
|
||||
while (i < self.windows.items.len) {
|
||||
const window = self.windows.items[i];
|
||||
if (window.shouldClose()) {
|
||||
window.destroy();
|
||||
_ = self.windows.swapRemove(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
i += 1;
|
||||
}
|
||||
|
||||
// Drain our mailbox
|
||||
try self.drainMailbox();
|
||||
}
|
||||
}
|
||||
|
||||
/// Drain the mailbox.
|
||||
fn drainMailbox(self: *App) !void {
|
||||
var drain = self.mailbox.drain();
|
||||
defer drain.deinit();
|
||||
|
||||
while (drain.next()) |message| {
|
||||
log.debug("mailbox message={}", .{message});
|
||||
switch (message) {
|
||||
.new_window => unreachable,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The message types that can be sent to the app thread.
|
||||
pub const Message = union(enum) {
|
||||
/// Create a new terminal window.
|
||||
new_window: void,
|
||||
};
|
||||
|
@ -136,6 +136,10 @@ pub fn create(alloc: Allocator, config: *const Config) !*Window {
|
||||
};
|
||||
|
||||
// Find all the fonts for this window
|
||||
//
|
||||
// Future: we can share the font group amongst all windows to save
|
||||
// some new window init time and some memory. This will require making
|
||||
// thread-safe changes to font structs.
|
||||
var font_lib = try font.Library.init();
|
||||
errdefer font_lib.deinit();
|
||||
var font_group = try alloc.create(font.GroupCache);
|
||||
|
Reference in New Issue
Block a user