From 962be81f710b50df9ab005ec64546c9459bc0e49 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 5 Jan 2024 21:03:37 -0800 Subject: [PATCH 1/9] core: add Apple Color Emoji on macOS if its available --- src/Surface.zig | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/Surface.zig b/src/Surface.zig index 0ed3b47d3..dbc800654 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -410,6 +410,21 @@ pub fn init( _ = try group.addFace(.bold_italic, .{ .deferred = face }); } else log.warn("font-family-bold-italic not found: {s}", .{family}); } + + // On macOS, always search for and add the Apple Emoji font + // as our preferred emoji font for fallback. We do this in case + // people add other emoji fonts to their system, we always want to + // prefer the official one. Users can override this by explicitly + // specifying a font-family for emoji. + if (comptime builtin.os.tag == .macos) { + var disco_it = try disco.discover(alloc, .{ + .family = "Apple Color Emoji", + }); + defer disco_it.deinit(); + if (try disco_it.next()) |face| { + _ = try group.addFace(.regular, .{ .fallback_deferred = face }); + } + } } // Our built-in font will be used as a backup From efd196e5c92b1b6d8c03373e07018d0dc2125f56 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 5 Jan 2024 21:08:39 -0800 Subject: [PATCH 2/9] pkg/freetype: unknown errors should be reported, not unreachable --- pkg/freetype/errors.zig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/freetype/errors.zig b/pkg/freetype/errors.zig index e4f98db87..3fe6dccb8 100644 --- a/pkg/freetype/errors.zig +++ b/pkg/freetype/errors.zig @@ -94,6 +94,7 @@ pub const Error = error{ BbxTooBig, CorruptedFontHeader, CorruptedFontGlyphs, + UnknownFreetypeError, }; pub fn intToError(err: c_int) Error!void { @@ -188,7 +189,7 @@ pub fn intToError(err: c_int) Error!void { c.FT_Err_Bbx_Too_Big => Error.BbxTooBig, c.FT_Err_Corrupted_Font_Header => Error.CorruptedFontHeader, c.FT_Err_Corrupted_Font_Glyphs => Error.CorruptedFontGlyphs, - else => unreachable, + else => Error.UnknownFreetypeError, }; } From 0200f7955432ddcda8dc7d1c2acc583d28df54e8 Mon Sep 17 00:00:00 2001 From: "Jeffrey C. Ollie" Date: Fri, 5 Jan 2024 23:44:53 -0600 Subject: [PATCH 3/9] Include the git commit hash in the Nix package. --- flake.nix | 2 ++ nix/package.nix | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index b3bcd07c9..0536b5247 100644 --- a/flake.nix +++ b/flake.nix @@ -31,6 +31,7 @@ }; outputs = { + self, nixpkgs-unstable, nixpkgs-stable, nixpkgs-zig-0-12, @@ -54,6 +55,7 @@ packages.${system} = rec { ghostty = pkgs-stable.callPackage ./nix/package.nix { inherit (pkgs-zig-0-12) zig_0_12; + revision = self.shortRev or self.dirtyShortRev or "dirty"; }; default = ghostty; }; diff --git a/nix/package.nix b/nix/package.nix index ea471dd0e..6b86ea75b 100644 --- a/nix/package.nix +++ b/nix/package.nix @@ -1,4 +1,5 @@ { + self, lib, stdenv, bzip2, @@ -23,6 +24,7 @@ ncurses, pkg-config, zig_0_12, + revision ? "dirty", }: let # The Zig hook has no way to select the release type without actual # overriding of the default flags. @@ -121,7 +123,7 @@ in dontConfigure = true; - zigBuildFlags = "-Dversion-string=${finalAttrs.version}"; + zigBuildFlags = "-Dversion-string=${finalAttrs.version}-${revision}"; preBuild = '' rm -rf $ZIG_GLOBAL_CACHE_DIR From f09901f236bc6b423f2a5e96fc674465684b81da Mon Sep 17 00:00:00 2001 From: "Jeffrey C. Ollie" Date: Sat, 6 Jan 2024 00:08:30 -0600 Subject: [PATCH 4/9] Include '-nix' in the version string to distinguish Nix builds. --- nix/package.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/package.nix b/nix/package.nix index 6b86ea75b..0e4d1d4b7 100644 --- a/nix/package.nix +++ b/nix/package.nix @@ -123,7 +123,7 @@ in dontConfigure = true; - zigBuildFlags = "-Dversion-string=${finalAttrs.version}-${revision}"; + zigBuildFlags = "-Dversion-string=${finalAttrs.version}-${revision}-nix"; preBuild = '' rm -rf $ZIG_GLOBAL_CACHE_DIR From 8a816dc5ef328472b443f22160dd1c902b1c623d Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 6 Jan 2024 12:30:44 -0800 Subject: [PATCH 5/9] os: mac app launched with bundle env var is treated as desktop launch --- src/os/desktop.zig | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/os/desktop.zig b/src/os/desktop.zig index ed4f977d9..6475c278e 100644 --- a/src/os/desktop.zig +++ b/src/os/desktop.zig @@ -19,7 +19,15 @@ pub fn launchedFromDesktop() bool { return switch (builtin.os.tag) { // macOS apps launched from finder or `open` always have the init // process as their parent. - .macos => c.getppid() == 1, + .macos => macos: { + // This special case is so that if we launch the app via the + // app bundle (i.e. via open) then we still treat it as if it + // was launched from the desktop. + if (build_config.artifact == .lib and + std.os.getenv("GHOSTTY_MAC_APP") != null) break :macos true; + + break :macos c.getppid() == 1; + }, // On Linux, GTK sets GIO_LAUNCHED_DESKTOP_FILE and // GIO_LAUNCHED_DESKTOP_FILE_PID. We only check the latter to see if From d65fbba39e57f723fa6a93c393768b9c9dd2d60a Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 6 Jan 2024 12:31:01 -0800 Subject: [PATCH 6/9] config: do not load command from SHELL when launched from desktop Fixes #139 From the issue: Looking into this now, I think I figured out the broken logic. When launching from open, the parent process of Ghostty is launchd which appears to set your SHELL env var to your configured shell when logging in. That's why a restart fixes it. However, I believe directory services (the macOS equivalent to /etc/passwd) is updated in real time. Ghostty does read directory services but at a lower priority than SHELL. This logic makes sense for CLI-launched terminals but not desktop-launched. From a CLI you want the terminal you're launching to probably inherit the shell from the CLI you launched it from. (Note that using open explicitly forces a launchd-style launch so it quacks as if it was double-clicked on the desktop). In conclusion, I believe the correct logic is to invert the priority on SHELL vs directory services when Ghostty detects it was launched from launchd. We already have this detection logic in Ghostty because we use it for a number of other things as well, so this should be easy to fix. I'll work on it later today. --- src/config/Config.zig | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/config/Config.zig b/src/config/Config.zig index 025d09412..9881580b9 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -1674,16 +1674,22 @@ pub fn finalize(self: *Config) !void { // set to /bin/sh. if (self.command) |cmd| log.info("shell src=config value={s}", .{cmd}) - else { - if (!internal_os.isFlatpak()) { - if (std.process.getEnvVarOwned(alloc, "SHELL")) |value| { - log.info("default shell source=env value={s}", .{value}); - self.command = value; + else shell_env: { + // Flatpak always gets its shell from outside the sandbox + if (internal_os.isFlatpak()) break :shell_env; - // If we don't need the working directory, then we can exit now. - if (!wd_home) break :command; - } else |_| {} - } + // If we were launched from the desktop, our SHELL env var + // will represent our SHELL at login time. We want to use the + // latest shell from /etc/passwd or directory services. + if (internal_os.launchedFromDesktop()) break :shell_env; + + if (std.process.getEnvVarOwned(alloc, "SHELL")) |value| { + log.info("default shell source=env value={s}", .{value}); + self.command = value; + + // If we don't need the working directory, then we can exit now. + if (!wd_home) break :command; + } else |_| {} } switch (builtin.os.tag) { From 6626c315d7f92cda0c10d3c09e1187fabdd42404 Mon Sep 17 00:00:00 2001 From: "Jeffrey C. Ollie" Date: Sat, 6 Jan 2024 16:30:40 -0600 Subject: [PATCH 7/9] In some cases, 'self' would not be passed to the package. It's not necessary so remove it. --- nix/package.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/nix/package.nix b/nix/package.nix index 0e4d1d4b7..62d28b934 100644 --- a/nix/package.nix +++ b/nix/package.nix @@ -1,5 +1,4 @@ { - self, lib, stdenv, bzip2, From f447e6f9df87fd7942630261151935b8dedcad65 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 6 Jan 2024 18:57:42 -0800 Subject: [PATCH 8/9] font: insert blank cells for multi-cell ligatures for styling Up to this point, every font I've experienced with ligatures has replaced the codepoints that were replaced for combining with a space. For example, if a font has a ligature for "!=" to turn it into a glyph, it'd shape to `[not equal glyph, space]`, so it'd still take up two cells, allowing us to style both. Monaspace, however, does not do this. It turns "!=" into `[not equal glyph]` so styles like backgrounds, underlines, etc. were not extending. This commit detects multi-cell glyphs and inserts synthetic blank cells so that styling returns. I decided to do this via synthetic blank cells instead of introducing a `cell_width` to the shaper result because this simplifies the renderers to assume each shaper cell is one cell. We can change this later if we need to. Annoyingly, this does make the shaper slightly slower for EVERYONE to accomodate one known font that behaves this way. I haven't benchmarked it but my belief is that the performance impact will be negligible because to figure out cell width we're only accessing subsequent cells so they're likely to be in the CPU cache and also 99% of cells are going to be width 1. --- src/font/res/MonaspaceNeon-Regular.otf | Bin 0 -> 73232 bytes src/font/shape.zig | 5 +- src/font/shaper/coretext.zig | 4 + src/font/shaper/harfbuzz.zig | 104 ++++++++++++++++++++++--- src/font/test.zig | 4 + src/renderer/Metal.zig | 4 +- src/renderer/OpenGL.zig | 4 +- 7 files changed, 110 insertions(+), 15 deletions(-) create mode 100644 src/font/res/MonaspaceNeon-Regular.otf diff --git a/src/font/res/MonaspaceNeon-Regular.otf b/src/font/res/MonaspaceNeon-Regular.otf new file mode 100644 index 0000000000000000000000000000000000000000..75aeb627f06eb3359fd646e972a9578b295d6e24 GIT binary patch literal 73232 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 1) { + // To make the renderer implementations simpler, we convert + // the extra spaces for width to blank cells. + for (1..cell_width) |j| { + try self.cell_buf.append(self.alloc, .{ + .x = @intCast(info_v.cluster + j), + .glyph_index = null, + }); + } + } + // const i = self.cell_buf.items.len - 1; // log.warn("i={} info={} pos={} cell={}", .{ i, info_v, pos_v, self.cell_buf.items[i] }); } @@ -334,7 +371,9 @@ test "shape inconsolata ligs" { count += 1; const cells = try shaper.shape(run); - try testing.expectEqual(@as(usize, 1), cells.len); + try testing.expectEqual(@as(usize, 2), cells.len); + try testing.expect(cells[0].glyph_index != null); + try testing.expect(cells[1].glyph_index == null); } try testing.expectEqual(@as(usize, 1), count); } @@ -351,7 +390,38 @@ test "shape inconsolata ligs" { count += 1; const cells = try shaper.shape(run); - try testing.expectEqual(@as(usize, 1), cells.len); + try testing.expectEqual(@as(usize, 3), cells.len); + try testing.expect(cells[0].glyph_index != null); + try testing.expect(cells[1].glyph_index == null); + try testing.expect(cells[2].glyph_index == null); + } + try testing.expectEqual(@as(usize, 1), count); + } +} + +test "shape monaspace ligs" { + const testing = std.testing; + const alloc = testing.allocator; + + var testdata = try testShaperWithFont(alloc, .monaspace_neon); + defer testdata.deinit(); + + { + var screen = try terminal.Screen.init(alloc, 3, 5, 0); + defer screen.deinit(); + try screen.testWriteString("==="); + + var shaper = &testdata.shaper; + var it = shaper.runIterator(testdata.cache, screen.getRow(.{ .screen = 0 }), null, null); + var count: usize = 0; + while (try it.next(alloc)) |run| { + count += 1; + + const cells = try shaper.shape(run); + try testing.expectEqual(@as(usize, 3), cells.len); + try testing.expect(cells[0].glyph_index != null); + try testing.expect(cells[1].glyph_index == null); + try testing.expect(cells[2].glyph_index == null); } try testing.expectEqual(@as(usize, 1), count); } @@ -376,7 +446,7 @@ test "shape emoji width" { count += 1; const cells = try shaper.shape(run); - try testing.expectEqual(@as(usize, 1), cells.len); + try testing.expectEqual(@as(usize, 2), cells.len); } try testing.expectEqual(@as(usize, 1), count); } @@ -411,7 +481,9 @@ test "shape emoji width long" { try testing.expectEqual(@as(u32, 4), shaper.hb_buf.getLength()); const cells = try shaper.shape(run); - try testing.expectEqual(@as(usize, 1), cells.len); + + // screen.testWriteString isn't grapheme aware, otherwise this is two + try testing.expectEqual(@as(usize, 5), cells.len); } try testing.expectEqual(@as(usize, 1), count); } @@ -574,9 +646,9 @@ test "shape box glyphs" { try testing.expectEqual(@as(u32, 2), shaper.hb_buf.getLength()); const cells = try shaper.shape(run); try testing.expectEqual(@as(usize, 2), cells.len); - try testing.expectEqual(@as(u32, 0x2500), cells[0].glyph_index); + try testing.expectEqual(@as(u32, 0x2500), cells[0].glyph_index.?); try testing.expectEqual(@as(u16, 0), cells[0].x); - try testing.expectEqual(@as(u32, 0x2501), cells[1].glyph_index); + try testing.expectEqual(@as(u32, 0x2501), cells[1].glyph_index.?); try testing.expectEqual(@as(u16, 1), cells[1].x); } try testing.expectEqual(@as(usize, 1), count); @@ -902,11 +974,23 @@ const TestShaper = struct { } }; +const TestFont = enum { + inconsolata, + monaspace_neon, +}; + /// Helper to return a fully initialized shaper. fn testShaper(alloc: Allocator) !TestShaper { - const testFont = @import("../test.zig").fontRegular; + return try testShaperWithFont(alloc, .inconsolata); +} + +fn testShaperWithFont(alloc: Allocator, font_req: TestFont) !TestShaper { const testEmoji = @import("../test.zig").fontEmoji; const testEmojiText = @import("../test.zig").fontEmojiText; + const testFont = switch (font_req) { + .inconsolata => @import("../test.zig").fontRegular, + .monaspace_neon => @import("../test.zig").fontMonaspaceNeon, + }; var lib = try Library.init(); errdefer lib.deinit(); diff --git a/src/font/test.zig b/src/font/test.zig index 06bdc40d2..09909691e 100644 --- a/src/font/test.zig +++ b/src/font/test.zig @@ -15,3 +15,7 @@ pub const fontVariable = @embedFile("res/Lilex-VF.ttf"); /// Cozette is a unique font because it embeds some emoji characters /// but has a text presentation. pub const fontCozette = @embedFile("res/CozetteVector.ttf"); + +/// Monaspace has weird ligature behaviors we want to test in our shapers +/// so we embed it here. +pub const fontMonaspaceNeon = @embedFile("res/MonaspaceNeon-Regular.otf"); diff --git a/src/renderer/Metal.zig b/src/renderer/Metal.zig index 81518c6e6..9c17702e0 100644 --- a/src/renderer/Metal.zig +++ b/src/renderer/Metal.zig @@ -1796,12 +1796,12 @@ fn updateCell( }; // If the cell has a character, draw it - if (cell.char > 0) { + if (cell.char > 0) fg: { // Render const glyph = try self.font_group.renderGlyph( self.alloc, shaper_run.font_index, - shaper_cell.glyph_index, + shaper_cell.glyph_index orelse break :fg, .{ .grid_metrics = self.grid_metrics, .thicken = self.config.font_thicken, diff --git a/src/renderer/OpenGL.zig b/src/renderer/OpenGL.zig index aea6991df..66fd966ee 100644 --- a/src/renderer/OpenGL.zig +++ b/src/renderer/OpenGL.zig @@ -1504,12 +1504,12 @@ fn updateCell( }; // If the cell has a character, draw it - if (cell.char > 0) { + if (cell.char > 0) fg: { // Render const glyph = try self.font_group.renderGlyph( self.alloc, shaper_run.font_index, - shaper_cell.glyph_index, + shaper_cell.glyph_index orelse break :fg, .{ .grid_metrics = self.grid_metrics, .thicken = self.config.font_thicken, From 383b7c5870bdebefeaa0aedbc0ae0f53170b09cb Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 7 Jan 2024 07:54:42 -0800 Subject: [PATCH 9/9] core: clear_screen binding doesn't consume on alt screen The clear_screen binding does nothing on the alternate screen already, but we were still marking the action as "performed" which caused the binding to be consumed. This meant that alt screen applications like neovim, tmux, etc. couldn't see "cmd+k" (default binding for clear_screen on macOS) without the Ghostty user unbinding it completely. We already have other bindings that do not consume only when they do not perform, such as `previous_tab` and `next_tab`. This extends the framework we built for that to this action. --- src/Surface.zig | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/Surface.zig b/src/Surface.zig index dbc800654..c78959288 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -2788,6 +2788,17 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool }, .clear_screen => { + // This is a duplicate of some of the logic in termio.clearScreen + // but we need to do this here so we can know the answer before + // we send the message. If the currently active screen is on the + // alternate screen then clear screen does nothing so we want to + // return false so the keybind can be unconsumed. + { + self.renderer_state.mutex.lock(); + defer self.renderer_state.mutex.unlock(); + if (self.io.terminal.active_screen == .alternate) return false; + } + _ = self.io_thread.mailbox.push(.{ .clear_screen = .{ .history = true }, }, .{ .forever = {} });