more crap

This commit is contained in:
Mitchell Hashimoto
2023-02-22 15:16:17 -08:00
parent 9e4560043a
commit 053748481a
7 changed files with 99 additions and 1758 deletions

View File

@ -164,9 +164,9 @@ fn drainMailbox(self: *App, rt_app: *apprt.runtime.App) !void {
switch (message) { switch (message) {
.new_window => |msg| { .new_window => |msg| {
_ = msg; // TODO _ = msg; // TODO
try rt_app.newWindow(); _ = try rt_app.newWindow();
}, },
.new_tab => |msg| try self.newTab(msg), .new_tab => |msg| try self.newTab(rt_app, msg),
.quit => try self.setQuit(), .quit => try self.setQuit(),
.surface_message => |msg| try self.surfaceMessage(msg.surface, msg.message), .surface_message => |msg| try self.surfaceMessage(msg.surface, msg.message),
} }
@ -174,19 +174,7 @@ fn drainMailbox(self: *App, rt_app: *apprt.runtime.App) !void {
} }
/// Create a new tab in the parent window /// Create a new tab in the parent window
fn newTab(self: *App, msg: Message.NewWindow) !void { fn newTab(self: *App, rt_app: *apprt.runtime.App, msg: Message.NewWindow) !void {
if (comptime !builtin.target.isDarwin()) {
log.warn("tabbing is not supported on this platform", .{});
return;
}
// In embedded mode, it is up to the embedder to implement tabbing
// on their own.
if (comptime build_config.artifact != .exe) {
log.warn("tabbing is not supported in embedded mode", .{});
return;
}
const parent = msg.parent orelse { const parent = msg.parent orelse {
log.warn("parent must be set in new_tab message", .{}); log.warn("parent must be set in new_tab message", .{});
return; return;
@ -198,11 +186,7 @@ fn newTab(self: *App, msg: Message.NewWindow) !void {
return; return;
} }
// Create the new window try rt_app.newTab(parent);
const window = try self.newWindow(msg);
// Add the window to our parent tab group
parent.addWindow(window);
} }
/// Start quitting /// Start quitting

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,7 @@ const objc = @import("objc");
const apprt = @import("../apprt.zig"); const apprt = @import("../apprt.zig");
const input = @import("../input.zig"); const input = @import("../input.zig");
const CoreApp = @import("../App.zig"); const CoreApp = @import("../App.zig");
const CoreWindow = @import("../Window.zig"); const CoreSurface = @import("../Surface.zig");
const log = std.log.scoped(.embedded_window); const log = std.log.scoped(.embedded_window);
@ -65,11 +65,11 @@ pub const App = struct {
} }
}; };
pub const Window = struct { pub const Surface = struct {
nsview: objc.Object, nsview: objc.Object,
core_win: *CoreWindow, core_win: *CoreSurface,
content_scale: apprt.ContentScale, content_scale: apprt.ContentScale,
size: apprt.WindowSize, size: apprt.SurfaceSize,
cursor_pos: apprt.CursorPos, cursor_pos: apprt.CursorPos,
opts: Options, opts: Options,
@ -84,7 +84,7 @@ pub const Window = struct {
scale_factor: f64 = 1, scale_factor: f64 = 1,
}; };
pub fn init(app: *const CoreApp, core_win: *CoreWindow, opts: Options) !Window { pub fn init(app: *const CoreApp, core_win: *CoreSurface, opts: Options) !Surface {
_ = app; _ = app;
return .{ return .{
@ -100,68 +100,68 @@ pub const Window = struct {
}; };
} }
pub fn deinit(self: *Window) void { pub fn deinit(self: *Surface) void {
_ = self; _ = self;
} }
pub fn getContentScale(self: *const Window) !apprt.ContentScale { pub fn getContentScale(self: *const Surface) !apprt.ContentScale {
return self.content_scale; return self.content_scale;
} }
pub fn getSize(self: *const Window) !apprt.WindowSize { pub fn getSize(self: *const Surface) !apprt.SurfaceSize {
return self.size; return self.size;
} }
pub fn setSizeLimits(self: *Window, min: apprt.WindowSize, max_: ?apprt.WindowSize) !void { pub fn setSizeLimits(self: *Surface, min: apprt.SurfaceSize, max_: ?apprt.SurfaceSize) !void {
_ = self; _ = self;
_ = min; _ = min;
_ = max_; _ = max_;
} }
pub fn setTitle(self: *Window, slice: [:0]const u8) !void { pub fn setTitle(self: *Surface, slice: [:0]const u8) !void {
self.core_win.app.runtime.opts.set_title( self.core_win.app.runtime.opts.set_title(
self.opts.userdata, self.opts.userdata,
slice.ptr, slice.ptr,
); );
} }
pub fn getClipboardString(self: *const Window) ![:0]const u8 { pub fn getClipboardString(self: *const Surface) ![:0]const u8 {
const ptr = self.core_win.app.runtime.opts.read_clipboard(self.opts.userdata); const ptr = self.core_win.app.runtime.opts.read_clipboard(self.opts.userdata);
return std.mem.sliceTo(ptr, 0); return std.mem.sliceTo(ptr, 0);
} }
pub fn setClipboardString(self: *const Window, val: [:0]const u8) !void { pub fn setClipboardString(self: *const Surface, val: [:0]const u8) !void {
self.core_win.app.runtime.opts.write_clipboard(self.opts.userdata, val.ptr); self.core_win.app.runtime.opts.write_clipboard(self.opts.userdata, val.ptr);
} }
pub fn setShouldClose(self: *Window) void { pub fn setShouldClose(self: *Surface) void {
_ = self; _ = self;
} }
pub fn shouldClose(self: *const Window) bool { pub fn shouldClose(self: *const Surface) bool {
_ = self; _ = self;
return false; return false;
} }
pub fn getCursorPos(self: *const Window) !apprt.CursorPos { pub fn getCursorPos(self: *const Surface) !apprt.CursorPos {
return self.cursor_pos; return self.cursor_pos;
} }
pub fn refresh(self: *Window) void { pub fn refresh(self: *Surface) void {
self.core_win.refreshCallback() catch |err| { self.core_win.refreshCallback() catch |err| {
log.err("error in refresh callback err={}", .{err}); log.err("error in refresh callback err={}", .{err});
return; return;
}; };
} }
pub fn updateContentScale(self: *Window, x: f64, y: f64) void { pub fn updateContentScale(self: *Surface, x: f64, y: f64) void {
self.content_scale = .{ self.content_scale = .{
.x = @floatCast(f32, x), .x = @floatCast(f32, x),
.y = @floatCast(f32, y), .y = @floatCast(f32, y),
}; };
} }
pub fn updateSize(self: *Window, width: u32, height: u32) void { pub fn updateSize(self: *Surface, width: u32, height: u32) void {
self.size = .{ self.size = .{
.width = width, .width = width,
.height = height, .height = height,
@ -175,7 +175,7 @@ pub const Window = struct {
} }
pub fn mouseButtonCallback( pub fn mouseButtonCallback(
self: *const Window, self: *const Surface,
action: input.MouseButtonState, action: input.MouseButtonState,
button: input.MouseButton, button: input.MouseButton,
mods: input.Mods, mods: input.Mods,
@ -186,14 +186,14 @@ pub const Window = struct {
}; };
} }
pub fn scrollCallback(self: *const Window, xoff: f64, yoff: f64) void { pub fn scrollCallback(self: *const Surface, xoff: f64, yoff: f64) void {
self.core_win.scrollCallback(xoff, yoff) catch |err| { self.core_win.scrollCallback(xoff, yoff) catch |err| {
log.err("error in scroll callback err={}", .{err}); log.err("error in scroll callback err={}", .{err});
return; return;
}; };
} }
pub fn cursorPosCallback(self: *Window, x: f64, y: f64) void { pub fn cursorPosCallback(self: *Surface, x: f64, y: f64) void {
// Convert our unscaled x/y to scaled. // Convert our unscaled x/y to scaled.
self.cursor_pos = self.core_win.window.cursorPosToPixels(.{ self.cursor_pos = self.core_win.window.cursorPosToPixels(.{
.x = @floatCast(f32, x), .x = @floatCast(f32, x),
@ -213,7 +213,7 @@ pub const Window = struct {
} }
pub fn keyCallback( pub fn keyCallback(
self: *const Window, self: *const Surface,
action: input.Action, action: input.Action,
key: input.Key, key: input.Key,
mods: input.Mods, mods: input.Mods,
@ -225,7 +225,7 @@ pub const Window = struct {
}; };
} }
pub fn charCallback(self: *const Window, cp_: u32) void { pub fn charCallback(self: *const Surface, cp_: u32) void {
const cp = std.math.cast(u21, cp_) orelse return; const cp = std.math.cast(u21, cp_) orelse return;
self.core_win.charCallback(cp) catch |err| { self.core_win.charCallback(cp) catch |err| {
log.err("error in char callback err={}", .{err}); log.err("error in char callback err={}", .{err});
@ -233,7 +233,7 @@ pub const Window = struct {
}; };
} }
pub fn focusCallback(self: *const Window, focused: bool) void { pub fn focusCallback(self: *const Surface, focused: bool) void {
self.core_win.focusCallback(focused) catch |err| { self.core_win.focusCallback(focused) catch |err| {
log.err("error in focus callback err={}", .{err}); log.err("error in focus callback err={}", .{err});
return; return;
@ -242,7 +242,7 @@ pub const Window = struct {
/// The cursor position from the host directly is in screen coordinates but /// The cursor position from the host directly is in screen coordinates but
/// all our interface works in pixels. /// all our interface works in pixels.
fn cursorPosToPixels(self: *const Window, pos: apprt.CursorPos) !apprt.CursorPos { fn cursorPosToPixels(self: *const Surface, pos: apprt.CursorPos) !apprt.CursorPos {
const scale = try self.getContentScale(); const scale = try self.getContentScale();
return .{ .x = pos.x * scale.x, .y = pos.y * scale.y }; return .{ .x = pos.x * scale.x, .y = pos.y * scale.y };
} }

View File

@ -76,7 +76,7 @@ pub const App = struct {
} }
/// Create a new window for the app. /// Create a new window for the app.
pub fn newWindow(self: *App) !void { pub fn newWindow(self: *App) !*Surface {
// Grab a surface allocation because we're going to need it. // Grab a surface allocation because we're going to need it.
const surface = try self.app.surface_pool.create(); const surface = try self.app.surface_pool.create();
errdefer self.app.surface_pool.destroy(surface); errdefer self.app.surface_pool.destroy(surface);
@ -84,6 +84,42 @@ pub const App = struct {
// Create the surface -- because windows are surfaces for glfw. // Create the surface -- because windows are surfaces for glfw.
try surface.init(self); try surface.init(self);
errdefer surface.deinit(); errdefer surface.deinit();
return surface;
}
/// Create a new tab in the parent surface.
pub fn newTab(self: *App, parent: *CoreSurface) !void {
if (!Darwin.enabled) {
log.warn("tabbing is not supported on this platform", .{});
return;
}
// Create the new window
const window = try self.newWindow();
// Add the new window the parent window
const parent_win = glfwNative.getCocoaWindow(parent.rt_surface.window).?;
const other_win = glfwNative.getCocoaWindow(window.window).?;
const NSWindowOrderingMode = enum(isize) { below = -1, out = 0, above = 1 };
const nswindow = objc.Object.fromId(parent_win);
nswindow.msgSend(void, objc.sel("addTabbedWindow:ordered:"), .{
objc.Object.fromId(other_win),
NSWindowOrderingMode.above,
});
// Adding a new tab can cause the tab bar to appear which changes
// our viewport size. We need to call the size callback in order to
// update values. For example, we need this to set the proper mouse selection
// point in the grid.
const size = parent.rt_surface.getSize() catch |err| {
log.err("error querying window size for size callback on new tab err={}", .{err});
return;
};
parent.sizeCallback(size) catch |err| {
log.err("error in size callback from new tab err={}", .{err});
return;
};
} }
/// Close the given surface. /// Close the given surface.

View File

@ -6,7 +6,7 @@ const assert = std.debug.assert;
const Allocator = std.mem.Allocator; const Allocator = std.mem.Allocator;
const apprt = @import("../apprt.zig"); const apprt = @import("../apprt.zig");
const CoreApp = @import("../App.zig"); const CoreApp = @import("../App.zig");
const CoreWindow = @import("../Window.zig"); const CoreSurface = @import("../Surface.zig");
pub const c = @cImport({ pub const c = @cImport({
@cInclude("gtk/gtk.h"); @cInclude("gtk/gtk.h");
@ -147,10 +147,10 @@ pub const App = struct {
} }
}; };
pub const Window = struct { pub const Surface = struct {
pub const Options = struct {}; pub const Options = struct {};
pub fn init(app: *const CoreApp, core_win: *CoreWindow, opts: Options) !Window { pub fn init(app: *const CoreApp, core_win: *CoreSurface, opts: Options) !Surface {
_ = app; _ = app;
_ = core_win; _ = core_win;
_ = opts; _ = opts;
@ -158,46 +158,46 @@ pub const Window = struct {
return .{}; return .{};
} }
pub fn deinit(self: *Window) void { pub fn deinit(self: *Surface) void {
_ = self; _ = self;
} }
pub fn setShouldClose(self: *Window) void { pub fn setShouldClose(self: *Surface) void {
_ = self; _ = self;
} }
pub fn shouldClose(self: *const Window) bool { pub fn shouldClose(self: *const Surface) bool {
_ = self; _ = self;
return false; return false;
} }
pub fn getContentScale(self: *const Window) !apprt.ContentScale { pub fn getContentScale(self: *const Surface) !apprt.ContentScale {
_ = self; _ = self;
return .{ .x = 1, .y = 1 }; return .{ .x = 1, .y = 1 };
} }
pub fn getSize(self: *const Window) !apprt.WindowSize { pub fn getSize(self: *const Surface) !apprt.SurfaceSize {
_ = self; _ = self;
return .{ .width = 800, .height = 600 }; return .{ .width = 800, .height = 600 };
} }
pub fn setSizeLimits(self: *Window, min: apprt.WindowSize, max_: ?apprt.WindowSize) !void { pub fn setSizeLimits(self: *Surface, min: apprt.SurfaceSize, max_: ?apprt.SurfaceSize) !void {
_ = self; _ = self;
_ = min; _ = min;
_ = max_; _ = max_;
} }
pub fn setTitle(self: *Window, slice: [:0]const u8) !void { pub fn setTitle(self: *Surface, slice: [:0]const u8) !void {
_ = self; _ = self;
_ = slice; _ = slice;
} }
pub fn getClipboardString(self: *const Window) ![:0]const u8 { pub fn getClipboardString(self: *const Surface) ![:0]const u8 {
_ = self; _ = self;
return ""; return "";
} }
pub fn setClipboardString(self: *const Window, val: [:0]const u8) !void { pub fn setClipboardString(self: *const Surface, val: [:0]const u8) !void {
_ = self; _ = self;
_ = val; _ = val;
} }

View File

@ -100,7 +100,7 @@ pub fn main() !void {
defer app_runtime.terminate(); defer app_runtime.terminate();
// Create an initial window // Create an initial window
try app_runtime.newWindow(); _ = try app_runtime.newWindow();
// Run the GUI event loop // Run the GUI event loop
try app_runtime.run(); try app_runtime.run();

View File

@ -16,7 +16,7 @@ const terminal = @import("../terminal/main.zig");
const renderer = @import("../renderer.zig"); const renderer = @import("../renderer.zig");
const math = @import("../math.zig"); const math = @import("../math.zig");
const DevMode = @import("../DevMode.zig"); const DevMode = @import("../DevMode.zig");
const Window = @import("../Window.zig"); const Surface = @import("../Surface.zig");
const assert = std.debug.assert; const assert = std.debug.assert;
const Allocator = std.mem.Allocator; const Allocator = std.mem.Allocator;
const Terminal = terminal.Terminal; const Terminal = terminal.Terminal;
@ -32,7 +32,7 @@ const log = std.log.scoped(.metal);
alloc: std.mem.Allocator, alloc: std.mem.Allocator,
/// The mailbox for communicating with the window. /// The mailbox for communicating with the window.
window_mailbox: Window.Mailbox, surface_mailbox: apprt.surface.Mailbox,
/// Current cell dimensions for this grid. /// Current cell dimensions for this grid.
cell_size: renderer.CellSize, cell_size: renderer.CellSize,
@ -135,8 +135,8 @@ pub fn glfwWindowHints() glfw.Window.Hints {
/// This is called early right after window creation to setup our /// This is called early right after window creation to setup our
/// window surface as necessary. /// window surface as necessary.
pub fn windowInit(win: apprt.runtime.Window) !void { pub fn surfaceInit(surface: *apprt.Surface) !void {
_ = win; _ = surface;
// We don't do anything else here because we want to set everything // We don't do anything else here because we want to set everything
// else up during actual initialization. // else up during actual initialization.
@ -240,7 +240,7 @@ pub fn init(alloc: Allocator, options: renderer.Options) !Metal {
return Metal{ return Metal{
.alloc = alloc, .alloc = alloc,
.window_mailbox = options.window_mailbox, .surface_mailbox = options.surface_mailbox,
.cell_size = .{ .width = metrics.cell_width, .height = metrics.cell_height }, .cell_size = .{ .width = metrics.cell_width, .height = metrics.cell_height },
.padding = options.padding, .padding = options.padding,
.focused = true, .focused = true,
@ -304,7 +304,7 @@ pub fn deinit(self: *Metal) void {
/// This is called just prior to spinning up the renderer thread for /// This is called just prior to spinning up the renderer thread for
/// final main thread setup requirements. /// final main thread setup requirements.
pub fn finalizeWindowInit(self: *const Metal, win: apprt.runtime.Window) !void { pub fn finalizeSurfaceInit(self: *const Metal, surface: *apprt.Surface) !void {
const Info = struct { const Info = struct {
view: objc.Object, view: objc.Object,
scaleFactor: f64, scaleFactor: f64,
@ -315,7 +315,7 @@ pub fn finalizeWindowInit(self: *const Metal, win: apprt.runtime.Window) !void {
apprt.glfw => info: { apprt.glfw => info: {
// Everything in glfw is window-oriented so we grab the backing // Everything in glfw is window-oriented so we grab the backing
// window, then derive everything from that. // window, then derive everything from that.
const nswindow = objc.Object.fromId(glfwNative.getCocoaWindow(win.window).?); const nswindow = objc.Object.fromId(glfwNative.getCocoaWindow(surface.window).?);
const contentView = objc.Object.fromId(nswindow.getProperty(?*anyopaque, "contentView").?); const contentView = objc.Object.fromId(nswindow.getProperty(?*anyopaque, "contentView").?);
const scaleFactor = nswindow.getProperty(macos.graphics.c.CGFloat, "backingScaleFactor"); const scaleFactor = nswindow.getProperty(macos.graphics.c.CGFloat, "backingScaleFactor");
break :info .{ break :info .{
@ -325,8 +325,8 @@ pub fn finalizeWindowInit(self: *const Metal, win: apprt.runtime.Window) !void {
}, },
apprt.embedded => .{ apprt.embedded => .{
.view = win.nsview, .view = surface.nsview,
.scaleFactor = @floatCast(f64, win.content_scale.x), .scaleFactor = @floatCast(f64, surface.content_scale.x),
}, },
else => @compileError("unsupported apprt for metal"), else => @compileError("unsupported apprt for metal"),
@ -344,11 +344,11 @@ pub fn finalizeWindowInit(self: *const Metal, win: apprt.runtime.Window) !void {
} }
/// This is called if this renderer runs DevMode. /// This is called if this renderer runs DevMode.
pub fn initDevMode(self: *const Metal, win: apprt.runtime.Window) !void { pub fn initDevMode(self: *const Metal, surface: *apprt.Surface) !void {
if (DevMode.enabled) { if (DevMode.enabled) {
// Initialize for our window // Initialize for our window
assert(imgui.ImplGlfw.initForOther( assert(imgui.ImplGlfw.initForOther(
@ptrCast(*imgui.ImplGlfw.GLFWWindow, win.window.handle), @ptrCast(*imgui.ImplGlfw.GLFWWindow, surface.window.handle),
true, true,
)); ));
assert(imgui.ImplMetal.init(self.device.value)); assert(imgui.ImplMetal.init(self.device.value));
@ -366,9 +366,9 @@ pub fn deinitDevMode(self: *const Metal) void {
} }
/// Callback called by renderer.Thread when it begins. /// Callback called by renderer.Thread when it begins.
pub fn threadEnter(self: *const Metal, win: apprt.runtime.Window) !void { pub fn threadEnter(self: *const Metal, surface: *apprt.Surface) !void {
_ = self; _ = self;
_ = win; _ = surface;
// Metal requires no per-thread state. // Metal requires no per-thread state.
} }
@ -442,7 +442,7 @@ pub fn setFontSize(self: *Metal, size: font.face.DesiredSize) !void {
}; };
// Notify the window that the cell size changed. // Notify the window that the cell size changed.
_ = self.window_mailbox.push(.{ _ = self.surface_mailbox.push(.{
.cell_size = new_cell_size, .cell_size = new_cell_size,
}, .{ .forever = {} }); }, .{ .forever = {} });
} }
@ -450,10 +450,10 @@ pub fn setFontSize(self: *Metal, size: font.face.DesiredSize) !void {
/// The primary render callback that is completely thread-safe. /// The primary render callback that is completely thread-safe.
pub fn render( pub fn render(
self: *Metal, self: *Metal,
win: apprt.runtime.Window, surface: *apprt.Surface,
state: *renderer.State, state: *renderer.State,
) !void { ) !void {
_ = win; _ = surface;
// Data we extract out of the critical area. // Data we extract out of the critical area.
const Critical = struct { const Critical = struct {
@ -533,8 +533,8 @@ pub fn render(
critical.draw_cursor, critical.draw_cursor,
); );
// Get our surface (CAMetalDrawable) // Get our drawable (CAMetalDrawable)
const surface = self.swapchain.msgSend(objc.Object, objc.sel("nextDrawable"), .{}); const drawable = self.swapchain.msgSend(objc.Object, objc.sel("nextDrawable"), .{});
// If our font atlas changed, sync the texture data // If our font atlas changed, sync the texture data
if (self.font_group.atlas_greyscale.modified) { if (self.font_group.atlas_greyscale.modified) {
@ -572,7 +572,7 @@ pub fn render(
// Ghostty in XCode in debug mode it returns a CaptureMTLDrawable // Ghostty in XCode in debug mode it returns a CaptureMTLDrawable
// which ironically doesn't implement CAMetalDrawable as a // which ironically doesn't implement CAMetalDrawable as a
// property so we just send a message. // property so we just send a message.
const texture = surface.msgSend(objc.c.id, objc.sel("texture"), .{}); const texture = drawable.msgSend(objc.c.id, objc.sel("texture"), .{});
attachment.setProperty("loadAction", @enumToInt(MTLLoadAction.clear)); attachment.setProperty("loadAction", @enumToInt(MTLLoadAction.clear));
attachment.setProperty("storeAction", @enumToInt(MTLStoreAction.store)); attachment.setProperty("storeAction", @enumToInt(MTLStoreAction.store));
attachment.setProperty("texture", texture); attachment.setProperty("texture", texture);
@ -656,7 +656,7 @@ pub fn render(
} }
} }
buffer.msgSend(void, objc.sel("presentDrawable:"), .{surface.value}); buffer.msgSend(void, objc.sel("presentDrawable:"), .{drawable.value});
buffer.msgSend(void, objc.sel("commit"), .{}); buffer.msgSend(void, objc.sel("commit"), .{});
} }