summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacob Sandlund <jacob@jacobsandlund.com>2025-08-23 09:16:11 -0400
committerJacob Sandlund <jacob@jacobsandlund.com>2025-08-23 09:16:11 -0400
commit39ecfe921177a6da369ab80a7b2d4a65bb6d2a01 (patch)
tree6a4bc43b1c63fbd31dad987aee70f70a7aa68f14
parent3c61aaca2aed11e909b1edb075638253037350e3 (diff)
parentc014dd79f6f4526c1883f7bdbffda124ecf70f77 (diff)
Merge remote-tracking branch 'upstream/main' into jacob/uucode
-rw-r--r--build.zig.zon4
-rw-r--r--build.zig.zon.json6
-rw-r--r--build.zig.zon.nix6
-rw-r--r--build.zig.zon.txt2
-rw-r--r--flatpak/zig-packages.json6
-rw-r--r--macos/Sources/Features/QuickTerminal/QuickTerminalController.swift15
-rw-r--r--macos/Sources/Features/QuickTerminal/QuickTerminalWindow.swift15
-rw-r--r--macos/Sources/Features/Terminal/BaseTerminalController.swift4
-rw-r--r--macos/Sources/Features/Terminal/TerminalController.swift10
-rw-r--r--po/es_AR.UTF-8.po12
-rw-r--r--src/Surface.zig89
-rw-r--r--src/os/i18n.zig7
12 files changed, 125 insertions, 51 deletions
diff --git a/build.zig.zon b/build.zig.zon
index b4dc58efb..b164175c8 100644
--- a/build.zig.zon
+++ b/build.zig.zon
@@ -20,8 +20,8 @@
},
.z2d = .{
// vancluever/z2d
- .url = "https://github.com/vancluever/z2d/archive/refs/tags/v0.7.1.tar.gz",
- .hash = "z2d-0.7.1-j5P_HhFQDQC6T5srG235r_nQpCrNwI15Gu2zqVrtUxN5",
+ .url = "https://github.com/vancluever/z2d/archive/refs/tags/v0.7.2.tar.gz",
+ .hash = "z2d-0.7.2-j5P_Hm1oDQDQsWpGfSCMARhowBnuTHlQ_sBfij6TuG7l",
.lazy = true,
},
.zig_objc = .{
diff --git a/build.zig.zon.json b/build.zig.zon.json
index 8b35e80e9..e1773f575 100644
--- a/build.zig.zon.json
+++ b/build.zig.zon.json
@@ -139,10 +139,10 @@
"url": "https://deps.files.ghostty.org/wuffs-122037b39d577ec2db3fd7b2130e7b69ef6cc1807d68607a7c232c958315d381b5cd.tar.gz",
"hash": "sha256-nkzSCr6W5sTG7enDBXEIhgEm574uLD41UVR2wlC+HBM="
},
- "z2d-0.7.1-j5P_HhFQDQC6T5srG235r_nQpCrNwI15Gu2zqVrtUxN5": {
+ "z2d-0.7.2-j5P_Hm1oDQDQsWpGfSCMARhowBnuTHlQ_sBfij6TuG7l": {
"name": "z2d",
- "url": "https://github.com/vancluever/z2d/archive/refs/tags/v0.7.1.tar.gz",
- "hash": "sha256-6ZqgrO/bcjgnuQcfq89VYptUUodsErM8Fz6nwBZhTJs="
+ "url": "https://github.com/vancluever/z2d/archive/refs/tags/v0.7.2.tar.gz",
+ "hash": "sha256-tWrLlEOU4/0ZOlzgGOXB08fW7sqfyAFf3rlv0wl9b/c="
},
"zf-0.10.3-OIRy8aiIAACLrBllz0zjxaH0aOe5oNm3KtEMyCntST-9": {
"name": "zf",
diff --git a/build.zig.zon.nix b/build.zig.zon.nix
index 50f2438c1..2d5fd8355 100644
--- a/build.zig.zon.nix
+++ b/build.zig.zon.nix
@@ -306,11 +306,11 @@ in
};
}
{
- name = "z2d-0.7.1-j5P_HhFQDQC6T5srG235r_nQpCrNwI15Gu2zqVrtUxN5";
+ name = "z2d-0.7.2-j5P_Hm1oDQDQsWpGfSCMARhowBnuTHlQ_sBfij6TuG7l";
path = fetchZigArtifact {
name = "z2d";
- url = "https://github.com/vancluever/z2d/archive/refs/tags/v0.7.1.tar.gz";
- hash = "sha256-6ZqgrO/bcjgnuQcfq89VYptUUodsErM8Fz6nwBZhTJs=";
+ url = "https://github.com/vancluever/z2d/archive/refs/tags/v0.7.2.tar.gz";
+ hash = "sha256-tWrLlEOU4/0ZOlzgGOXB08fW7sqfyAFf3rlv0wl9b/c=";
};
}
{
diff --git a/build.zig.zon.txt b/build.zig.zon.txt
index 4a22d98df..88a0ad813 100644
--- a/build.zig.zon.txt
+++ b/build.zig.zon.txt
@@ -33,4 +33,4 @@ https://github.com/mbadolato/iTerm2-Color-Schemes/archive/8b639f0c2605557bd23ba1
https://github.com/mitchellh/libxev/archive/7f803181b158a10fec8619f793e3b4df515566cb.tar.gz
https://github.com/mitchellh/zig-objc/archive/c9e917a4e15a983b672ca779c7985d738a2d517c.tar.gz
https://github.com/natecraddock/zf/archive/7aacbe6d155d64d15937ca95ca6c014905eb531f.tar.gz
-https://github.com/vancluever/z2d/archive/refs/tags/v0.7.1.tar.gz
+https://github.com/vancluever/z2d/archive/refs/tags/v0.7.2.tar.gz
diff --git a/flatpak/zig-packages.json b/flatpak/zig-packages.json
index 02d5ea1c7..80dcf4bc1 100644
--- a/flatpak/zig-packages.json
+++ b/flatpak/zig-packages.json
@@ -169,9 +169,9 @@
},
{
"type": "archive",
- "url": "https://github.com/vancluever/z2d/archive/refs/tags/v0.7.1.tar.gz",
- "dest": "vendor/p/z2d-0.7.1-j5P_HhFQDQC6T5srG235r_nQpCrNwI15Gu2zqVrtUxN5",
- "sha256": "e99aa0acefdb723827b9071fabcf55629b5452876c12b33c173ea7c016614c9b"
+ "url": "https://github.com/vancluever/z2d/archive/refs/tags/v0.7.2.tar.gz",
+ "dest": "vendor/p/z2d-0.7.2-j5P_Hm1oDQDQsWpGfSCMARhowBnuTHlQ_sBfij6TuG7l",
+ "sha256": "b56acb944394e3fd193a5ce018e5c1d3c7d6eeca9fc8015fdeb96fd3097d6ff7"
},
{
"type": "archive",
diff --git a/macos/Sources/Features/QuickTerminal/QuickTerminalController.swift b/macos/Sources/Features/QuickTerminal/QuickTerminalController.swift
index 3bd8bc18f..1f608f767 100644
--- a/macos/Sources/Features/QuickTerminal/QuickTerminalController.swift
+++ b/macos/Sources/Features/QuickTerminal/QuickTerminalController.swift
@@ -111,12 +111,27 @@ class QuickTerminalController: BaseTerminalController {
// Setup our initial size based on our configured position
position.setLoaded(window)
+ // Upon first adding this Window to its host view, older SwiftUI
+ // seems to have a "hiccup" and corrupts the frameRect,
+ // sometimes setting the size to zero, sometimes corrupting it.
+ // We pass the actual window's frame as "initial" frame directly
+ // to the window, so it can use that instead of the frameworks
+ // "interpretation"
+ if let qtWindow = window as? QuickTerminalWindow {
+ qtWindow.initialFrame = window.frame
+ }
+
// Setup our content
window.contentView = NSHostingView(rootView: TerminalView(
ghostty: self.ghostty,
viewModel: self,
delegate: self
))
+
+ // Clear out our frame at this point, the fixup from above is complete.
+ if let qtWindow = window as? QuickTerminalWindow {
+ qtWindow.initialFrame = nil
+ }
// Animate the window in
animateIn()
diff --git a/macos/Sources/Features/QuickTerminal/QuickTerminalWindow.swift b/macos/Sources/Features/QuickTerminal/QuickTerminalWindow.swift
index 005808a23..1a4170dbc 100644
--- a/macos/Sources/Features/QuickTerminal/QuickTerminalWindow.swift
+++ b/macos/Sources/Features/QuickTerminal/QuickTerminalWindow.swift
@@ -29,4 +29,19 @@ class QuickTerminalWindow: NSPanel {
// We don't want to activate the owning app when quick terminal is triggered.
self.styleMask.insert(.nonactivatingPanel)
}
+
+ /// This is set to the frame prior to setting `contentView`. This is purely a hack to workaround
+ /// bugs in older macOS versions (Ventura): https://github.com/ghostty-org/ghostty/pull/8026
+ var initialFrame: NSRect? = nil
+
+ override func setFrame(_ frameRect: NSRect, display flag: Bool) {
+ // Upon first adding this Window to its host view, older SwiftUI
+ // seems to have a "hiccup" and corrupts the frameRect,
+ // sometimes setting the size to zero, sometimes corrupting it.
+ // If we find we have cached the "initial" frame, use that instead
+ // the propagated one through the framework
+ //
+ // https://github.com/ghostty-org/ghostty/pull/8026
+ super.setFrame(initialFrame ?? frameRect, display: flag)
+ }
}
diff --git a/macos/Sources/Features/Terminal/BaseTerminalController.swift b/macos/Sources/Features/Terminal/BaseTerminalController.swift
index c93a9450d..ffe7997a6 100644
--- a/macos/Sources/Features/Terminal/BaseTerminalController.swift
+++ b/macos/Sources/Features/Terminal/BaseTerminalController.swift
@@ -290,8 +290,12 @@ class BaseTerminalController: NSWindowController,
alert.addButton(withTitle: "Cancel")
alert.alertStyle = .warning
alert.beginSheetModal(for: window) { response in
+ let alertWindow = alert.window
self.alert = nil
if response == .alertFirstButtonReturn {
+ // This is important so that we avoid losing focus when Stage
+ // Manager is used (#8336)
+ alertWindow.orderOut(nil)
completion()
}
}
diff --git a/macos/Sources/Features/Terminal/TerminalController.swift b/macos/Sources/Features/Terminal/TerminalController.swift
index ec56fb934..644a0c8ac 100644
--- a/macos/Sources/Features/Terminal/TerminalController.swift
+++ b/macos/Sources/Features/Terminal/TerminalController.swift
@@ -196,7 +196,12 @@ class TerminalController: BaseTerminalController, TabGroupCloseCoordinator.Contr
if let parent {
if parent.styleMask.contains(.fullScreen) {
- parent.toggleFullScreen(nil)
+ // If our previous window was fullscreen then we want our new window to
+ // be fullscreen. This behavior actually doesn't match the native tabbing
+ // behavior of macOS apps where new windows create tabs when in native
+ // fullscreen but this is how we've always done it. This matches iTerm2
+ // behavior.
+ c.toggleFullscreen(mode: .native)
} else if ghostty.config.windowFullscreen {
switch (ghostty.config.windowFullscreenMode) {
case .native:
@@ -747,6 +752,9 @@ class TerminalController: BaseTerminalController, TabGroupCloseCoordinator.Contr
alert.alertStyle = .warning
alert.beginSheetModal(for: alertWindow, completionHandler: { response in
if (response == .alertFirstButtonReturn) {
+ // This is important so that we avoid losing focus when Stage
+ // Manager is used (#8336)
+ alert.window.orderOut(nil)
closeAllWindowsImmediately()
}
})
diff --git a/po/es_AR.UTF-8.po b/po/es_AR.UTF-8.po
index 16f955355..496e0ebbf 100644
--- a/po/es_AR.UTF-8.po
+++ b/po/es_AR.UTF-8.po
@@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: com.mitchellh.ghostty\n"
"Report-Msgid-Bugs-To: m@mitchellh.com\n"
"POT-Creation-Date: 2025-07-22 17:18+0000\n"
-"PO-Revision-Date: 2025-05-19 20:17-0300\n"
+"PO-Revision-Date: 2025-08-22 09:35-0300\n"
"Last-Translator: Alan Moyano <alanmoyano203@gmail.com>\n"
"Language-Team: Argentinian <es@tp.org.es>\n"
"Language: es_AR\n"
@@ -208,12 +208,12 @@ msgstr "Permitir"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
msgid "Remember choice for this split"
-msgstr ""
+msgstr "Recordar elección para esta división"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
msgid "Reload configuration to show this prompt again"
-msgstr ""
+msgstr "Recargar la configuración para volver a mostrar este mensaje"
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
@@ -278,15 +278,15 @@ msgstr "Copiado al portapapeles"
#: src/apprt/gtk/Surface.zig:1268
msgid "Cleared clipboard"
-msgstr ""
+msgstr "Portapapeles limpiado"
#: src/apprt/gtk/Surface.zig:2525
msgid "Command succeeded"
-msgstr ""
+msgstr "Comando ejecutado correctamente"
#: src/apprt/gtk/Surface.zig:2527
msgid "Command failed"
-msgstr ""
+msgstr "El comando ha fallado"
#: src/apprt/gtk/Window.zig:216
msgid "Main Menu"
diff --git a/src/Surface.zig b/src/Surface.zig
index 2ab265cda..770c2daef 100644
--- a/src/Surface.zig
+++ b/src/Surface.zig
@@ -3555,26 +3555,7 @@ pub fn mouseButtonCallback(
};
switch (self.config.right_click_action) {
- .ignore => {
- // Return early to skip clearing the selection.
- try self.queueRender();
- return true;
- },
- .copy => {
- if (self.io.terminal.screen.selection) |sel| {
- self.copySelectionToClipboards(sel, &.{.standard});
- }
- },
- .@"copy-or-paste" => {
- if (self.io.terminal.screen.selection) |sel| {
- self.copySelectionToClipboards(sel, &.{.standard});
- } else {
- try self.startClipboardRequest(.standard, .paste);
- }
- },
- .paste => {
- try self.startClipboardRequest(.standard, .paste);
- },
+ .ignore => {},
.@"context-menu" => {
// If we already have a selection and the selection contains
// where we clicked then we don't want to modify the selection.
@@ -3588,12 +3569,45 @@ pub fn mouseButtonCallback(
const sel = screen.selectWord(pin) orelse break :sel;
try self.setSelection(sel);
try self.queueRender();
+
+ // Don't consume so that we show the context menu in apprt.
return false;
},
- }
+ .copy => {
+ if (self.io.terminal.screen.selection) |sel| {
+ self.copySelectionToClipboards(sel, &.{.standard});
+ }
- try self.setSelection(null);
- try self.queueRender();
+ try self.setSelection(null);
+ try self.queueRender();
+ },
+ .@"copy-or-paste" => if (self.io.terminal.screen.selection) |sel| {
+ self.copySelectionToClipboards(sel, &.{.standard});
+ try self.setSelection(null);
+ try self.queueRender();
+ } else {
+ // Pasting can trigger a lock grab in complete clipboard
+ // request so we need to unlock.
+ self.renderer_state.mutex.unlock();
+ defer self.renderer_state.mutex.lock();
+ try self.startClipboardRequest(.standard, .paste);
+
+ // We don't need to clear selection because we didn't have
+ // one to begin with.
+ },
+ .paste => {
+ // Before we yield the lock, clear our selection if we have
+ // one.
+ try self.setSelection(null);
+ try self.queueRender();
+
+ // Pasting can trigger a lock grab in complete clipboard
+ // request so we need to unlock.
+ self.renderer_state.mutex.unlock();
+ defer self.renderer_state.mutex.lock();
+ try self.startClipboardRequest(.standard, .paste);
+ },
+ }
// Consume the event such that the context menu is not displayed.
return true;
@@ -4494,19 +4508,32 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
const pos = try self.rt_surface.getCursorPos();
if (try self.linkAtPos(pos)) |link_info| {
- // Get the URL text from selection
- const url_text = (self.io.terminal.screen.selectionString(self.alloc, .{
- .sel = link_info[1],
- .trim = self.config.clipboard_trim_trailing_spaces,
- })) catch |err| {
- log.err("error reading url string err={}", .{err});
- return false;
+ const url_text = switch (link_info[0]) {
+ .open => url_text: {
+ // For regex links, get the text from selection
+ break :url_text (self.io.terminal.screen.selectionString(self.alloc, .{
+ .sel = link_info[1],
+ .trim = self.config.clipboard_trim_trailing_spaces,
+ })) catch |err| {
+ log.err("error reading url string err={}", .{err});
+ return false;
+ };
+ },
+
+ ._open_osc8 => url_text: {
+ // For OSC8 links, get the URI directly from hyperlink data
+ const uri = self.osc8URI(link_info[1].start()) orelse {
+ log.warn("failed to get URI for OSC8 hyperlink", .{});
+ return false;
+ };
+ break :url_text try self.alloc.dupeZ(u8, uri);
+ },
};
defer self.alloc.free(url_text);
self.rt_surface.setClipboardString(url_text, .standard, false) catch |err| {
log.err("error copying url to clipboard err={}", .{err});
- return true;
+ return false;
};
return true;
diff --git a/src/os/i18n.zig b/src/os/i18n.zig
index c6bce6fbf..29f7f6bc3 100644
--- a/src/os/i18n.zig
+++ b/src/os/i18n.zig
@@ -136,7 +136,12 @@ pub fn canonicalizeLocale(
buf: []u8,
locale: []const u8,
) error{NoSpaceLeft}![:0]const u8 {
- if (comptime !build_config.i18n) return locale;
+ if (comptime !build_config.i18n) {
+ if (buf.len < locale.len + 1) return error.NoSpaceLeft;
+ @memcpy(buf[0..locale.len], locale);
+ buf[locale.len] = 0;
+ return buf[0..locale.len :0];
+ }
// Fix zh locales for macOS
if (fixZhLocale(locale)) |fixed| {