From 0525c18f60ade456a484d9dc26e751d3c1b3993d Mon Sep 17 00:00:00 2001 From: Volodymyr Chernetskyi <19735328+chernetskyi@users.noreply.github.com> Date: Sun, 16 Aug 2026 09:02:05 +0200 Subject: [PATCH 01/21] i18n: adjust and extend Ukrainian translation --- po/uk.po | 384 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 208 insertions(+), 176 deletions(-) diff --git a/po/uk.po b/po/uk.po index 12372e266..901a02104 100644 --- a/po/uk.po +++ b/po/uk.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: com.mitchellh.ghostty\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n" "POT-Creation-Date: 2026-08-10 10:06-0500\n" -"PO-Revision-Date: 2026-02-18 13:14+0100\n" +"PO-Revision-Date: 2026-08-16 09:02+0100\n" "Last-Translator: Volodymyr Chernetskyi " "<19735328+chernetskyi@users.noreply.github.com>\n" "Language-Team: Ukrainian \n" @@ -42,7 +42,7 @@ msgstr "Дозволити" #: src/apprt/gtk/ui/1.4/clipboard-confirmation-dialog.blp:92 msgid "Remember choice for this split" -msgstr "Запамʼятати для цієї панелі" +msgstr "Запамʼятати вибір для цієї панелі" #: src/apprt/gtk/ui/1.4/clipboard-confirmation-dialog.blp:93 msgid "Reload configuration to show this prompt again" @@ -69,8 +69,8 @@ msgid "" "One or more configuration errors were found. Please review the errors below, " "and either reload your configuration or ignore these errors." msgstr "" -"Виявлено одну або декілька помилок налаштування. Будь ласка, перегляньте " -"помилки нижче і або перезавантажте налаштування, або проігноруйте ці помилки." +"Виявлено одну або кілька помилок налаштування. Будь ласка, перегляньте " +"помилки нижче і перезавантажте налаштування або проігноруйте ці помилки." #: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:12 msgid "Ignore" @@ -86,7 +86,7 @@ msgstr "Перезавантажити налаштування" msgid "" "⚠️ You're running a debug build of Ghostty! Performance will be degraded." msgstr "" -"⚠️ Ви використовуєте відладочну збірку Ghostty! Продуктивність буде погіршено." +"⚠️ Ви використовуєте збірку Ghostty для налагодження! Швидкодія буде нижчою." #: src/apprt/gtk/ui/1.5/inspector-window.blp:5 msgid "Ghostty: Terminal Inspector" @@ -118,12 +118,13 @@ msgid "" "through the content, but no input events will be sent to the running " "application." msgstr "" -"Цей термінал працює в режимі читання. Можна переглядати, виділяти і гортати " -"вміст, але ввід не буде передано до запущеної програми." +"Цей термінал працює в режимі «лише читання». Можна переглядати, виділяти і " +"прокручувати вміст, але події введення не передаватимуться до запущеної " +"програми." #: src/apprt/gtk/ui/1.2/surface.blp:112 msgid "Read-only" -msgstr "Тільки для читання" +msgstr "Лише читання" #: src/apprt/gtk/ui/1.2/surface.blp:316 src/apprt/gtk/ui/1.5/window.blp:203 msgid "Copy" @@ -175,7 +176,7 @@ msgstr "Нова панель праворуч" #: src/apprt/gtk/ui/1.2/surface.blp:377 msgid "Close Split" -msgstr "" +msgstr "Закрити панель" #: src/apprt/gtk/ui/1.2/surface.blp:383 msgid "Tab" @@ -203,7 +204,7 @@ msgstr "Вікно" #: src/apprt/gtk/ui/1.2/surface.blp:406 src/apprt/gtk/ui/1.5/window.blp:215 msgid "Change Window Title…" -msgstr "" +msgstr "Змінити заголовок вікна…" #: src/apprt/gtk/ui/1.2/surface.blp:411 src/apprt/gtk/ui/1.5/window.blp:220 #: src/input/command.zig:421 @@ -221,11 +222,11 @@ msgstr "Налаштування" #: src/apprt/gtk/ui/1.2/surface.blp:427 src/apprt/gtk/ui/1.5/window.blp:306 msgid "Open Configuration in OS Editor" -msgstr "" +msgstr "Відкрити налаштування в системному редакторі" #: src/apprt/gtk/ui/1.2/surface.blp:433 src/apprt/gtk/ui/1.5/window.blp:312 msgid "Open Configuration in New Window" -msgstr "" +msgstr "Відкрити налаштування в новому вікні" #: src/apprt/gtk/ui/1.5/title-dialog.blp:5 msgid "Leave blank to restore the default title." @@ -261,7 +262,7 @@ msgstr "Про Ghostty" #: src/apprt/gtk/ui/1.5/window.blp:331 src/input/command.zig:702 msgid "Quit" -msgstr "Завершити" +msgstr "Вийти" #: src/apprt/gtk/ui/1.5/command-palette.blp:17 msgid "Execute a command…" @@ -269,27 +270,27 @@ msgstr "Виконати команду…" #: src/apprt/gtk/class/application.zig:1767 msgid "The keybind was revoked by the system." -msgstr "" +msgstr "Привʼязка клавіш відкликана системою." #: src/apprt/gtk/class/application.zig:1769 msgid "The keybind was denied by the system." -msgstr "" +msgstr "Привʼязка клавіш відхилена системою." #: src/apprt/gtk/class/application.zig:1780 msgid "Global keybind unavailable" -msgstr "" +msgstr "Глобальна привʼязка клавіш недоступна" #: src/apprt/gtk/class/application.zig:2259 msgid "Export Terminal IO Events" -msgstr "" +msgstr "Експортувати події введення/виведення терміналу" #: src/apprt/gtk/class/application.zig:2262 msgid "Export" -msgstr "" +msgstr "Експортувати" #: src/apprt/gtk/class/application.zig:2783 msgid "Editing configuration file" -msgstr "" +msgstr "Редагування файлу налаштувань" #: src/apprt/gtk/class/clipboard_confirmation_dialog.zig:198 msgid "" @@ -316,12 +317,12 @@ msgid "" "Pasting this text into the terminal may be dangerous as it looks like some " "commands may be executed." msgstr "" -"Вставка цього тексту в термінал може бути небезпечною, бо схоже, що деякі " -"команди можуть бути виконані." +"Вставка цього тексту в термінал може бути небезпечною, оскільки, схоже, " +"деякі команди можуть бути виконані." #: src/apprt/gtk/class/close_confirmation_dialog.zig:184 msgid "Quit Ghostty?" -msgstr "Завершити Ghostty?" +msgstr "Вийти з Ghostty?" #: src/apprt/gtk/class/close_confirmation_dialog.zig:185 msgid "Close Tab?" @@ -375,7 +376,7 @@ msgstr "Змінити заголовок вкладки" #: src/apprt/gtk/class/title_dialog.zig:229 msgid "Change Window Title" -msgstr "" +msgstr "Змінити заголовок вікна" #: src/apprt/gtk/class/window.zig:1153 msgid "Reloaded the configuration" @@ -383,7 +384,7 @@ msgstr "Налаштування перезавантажено" #: src/apprt/gtk/class/window.zig:1830 msgid "Copied to clipboard" -msgstr "Скопійовано до буферa обміну" +msgstr "Скопійовано до буфера обміну" #: src/apprt/gtk/class/window.zig:1832 msgid "Cleared clipboard" @@ -395,710 +396,741 @@ msgstr "Розробники Ghostty" #: src/input/command.zig:149 msgid "Reset Terminal" -msgstr "" +msgstr "Скинути термінал" #: src/input/command.zig:150 msgid "Reset the terminal to a clean state." -msgstr "" +msgstr "Скинути стан терміналу." #: src/input/command.zig:155 msgid "Copy to Clipboard" -msgstr "" +msgstr "Скопіювати до буфера обміну" #: src/input/command.zig:156 msgid "" "Copy the selected text to the clipboard in both plain and styled formats." msgstr "" +"Скопіювати виділений текст до буфера обміну в звичайному і форматованому " +"виглядах одночасно." #: src/input/command.zig:159 msgid "Copy Selection as Plain Text to Clipboard" -msgstr "" +msgstr "Скопіювати виділене до буфера обміну як звичайний текст" #: src/input/command.zig:160 msgid "Copy the selected text as plain text to the clipboard." -msgstr "" +msgstr "Скопіювати виділений текст до буфера обміну як звичайний текст." #: src/input/command.zig:163 msgid "Copy Selection as ANSI Sequences to Clipboard" -msgstr "" +msgstr "Скопіювати виділене до буфера обміну як ANSI-послідовності" #: src/input/command.zig:164 msgid "Copy the selected text as ANSI escape sequences to the clipboard." -msgstr "" +msgstr "Скопіювати виділений текст до буфера обміну як ANSI-послідовності." #: src/input/command.zig:167 msgid "Copy Selection as HTML to Clipboard" -msgstr "" +msgstr "Скопіювати виділене до буфера обміну у форматі HTML" #: src/input/command.zig:168 msgid "Copy the selected text as HTML to the clipboard." -msgstr "" +msgstr "Скопіювати виділений текст до буфера обміну у форматі HTML." #: src/input/command.zig:173 msgid "Copy URL to Clipboard" -msgstr "" +msgstr "Скопіювати URL до буфера обміну" #: src/input/command.zig:174 msgid "Copy the URL under the cursor to the clipboard." -msgstr "" +msgstr "Скопіювати URL під вказівником до буфера обміну." #: src/input/command.zig:179 msgid "Copy Terminal Title to Clipboard" -msgstr "" +msgstr "Скопіювати заголовок терміналу до буфера обміну" #: src/input/command.zig:180 msgid "" "Copy the terminal title to the clipboard. If the terminal title is not set " "this has no effect." msgstr "" +"Скопіювати заголовок терміналу до буфера обміну. Якщо заголовку немає, то " +"нічого не відбудеться." #: src/input/command.zig:185 msgid "Paste from Clipboard" -msgstr "" +msgstr "Вставити з буфера обміну" #: src/input/command.zig:186 msgid "Paste the contents of the main clipboard." -msgstr "" +msgstr "Вставити вміст головного буфера обміну." #: src/input/command.zig:191 msgid "Paste from Selection" -msgstr "" +msgstr "Вставити виділене" #: src/input/command.zig:192 msgid "Paste the contents of the selection clipboard." -msgstr "" +msgstr "Вставити вміст буфера виділення." #: src/input/command.zig:197 msgid "Start Search" -msgstr "" +msgstr "Шукати" #: src/input/command.zig:198 msgid "Start a search if one isn't already active." -msgstr "" +msgstr "Почати пошук, якщо активного пошуку ще немає." #: src/input/command.zig:203 msgid "Search Selection" -msgstr "" +msgstr "Шукати виділене" #: src/input/command.zig:204 msgid "Start a search for the current text selection." -msgstr "" +msgstr "Почати пошук виділеного тексту." #: src/input/command.zig:209 msgid "End Search" -msgstr "" +msgstr "Завершити пошук" #: src/input/command.zig:210 msgid "End the current search if any and hide any GUI elements." -msgstr "" +msgstr "Завершити поточний пошук і сховати елементи інтерфейсу." #: src/input/command.zig:215 msgid "Next Search Result" -msgstr "" +msgstr "Наступна знахідка" #: src/input/command.zig:216 msgid "Navigate to the next search result, if any." -msgstr "" +msgstr "Перейти до наступної знахідки, якщо така є." #: src/input/command.zig:219 msgid "Previous Search Result" -msgstr "" +msgstr "Попередня знахідка" #: src/input/command.zig:220 msgid "Navigate to the previous search result, if any." -msgstr "" +msgstr "Перейти до попередньої знахідки, якщо така є." #: src/input/command.zig:225 msgid "Increase Font Size" -msgstr "" +msgstr "Збільшити розмір шрифту" #: src/input/command.zig:226 msgid "Increase the font size by 1 point." -msgstr "" +msgstr "Збільшити розмір шрифту на 1 пункт." #: src/input/command.zig:231 msgid "Decrease Font Size" -msgstr "" +msgstr "Зменшити розмір шрифту" #: src/input/command.zig:232 msgid "Decrease the font size by 1 point." -msgstr "" +msgstr "Зменшити розмір шрифту на 1 пункт." #: src/input/command.zig:237 msgid "Reset Font Size" -msgstr "" +msgstr "Скинути розмір шрифту" #: src/input/command.zig:238 msgid "Reset the font size to the default." -msgstr "" +msgstr "Скинути розмір шрифту до значення за замовчуванням." #: src/input/command.zig:243 msgid "Clear Screen" -msgstr "" +msgstr "Очистити екран" #: src/input/command.zig:244 msgid "Clear the screen and scrollback." -msgstr "" +msgstr "Очистити екран і буфер прокручування." #: src/input/command.zig:249 msgid "Select All" -msgstr "" +msgstr "Вибрати все" #: src/input/command.zig:250 msgid "Select all text on the screen." -msgstr "" +msgstr "Вибрати весь текст на екрані." #: src/input/command.zig:255 msgid "Scroll to Top" -msgstr "" +msgstr "Прокрутити до початку" #: src/input/command.zig:256 msgid "Scroll to the top of the screen." -msgstr "" +msgstr "Прокрутити до початку екрана." #: src/input/command.zig:261 msgid "Scroll to Bottom" -msgstr "" +msgstr "Прокрутити до кінця" #: src/input/command.zig:262 msgid "Scroll to the bottom of the screen." -msgstr "" +msgstr "Прокрутити до кінця екрана." #: src/input/command.zig:267 msgid "Scroll to Selection" -msgstr "" +msgstr "Прокрутити до виділеного" #: src/input/command.zig:268 msgid "Scroll to the selected text." -msgstr "" +msgstr "Прокрутити до виділеного тексту." #: src/input/command.zig:273 msgid "Scroll Page Up" -msgstr "" +msgstr "Прокрутити сторінку догори" #: src/input/command.zig:274 msgid "Scroll the screen up by a page." -msgstr "" +msgstr "Прокрутити екран на сторінку догори." #: src/input/command.zig:279 msgid "Scroll Page Down" -msgstr "" +msgstr "Прокрутити сторінку донизу" #: src/input/command.zig:280 msgid "Scroll the screen down by a page." -msgstr "" +msgstr "Прокрутити екран на сторінку донизу." #: src/input/command.zig:286 msgid "Copy Screen to Temporary File and Copy Path" -msgstr "" +msgstr "Зберегти екран до файлу і скопіювати шлях" #: src/input/command.zig:287 msgid "" "Copy the screen contents to a temporary file and copy the path to the " "clipboard." msgstr "" +"Зберегти вміст екрана до тимчасового файлу і скопіювати шлях до файлу до " +"буфера обміну." #: src/input/command.zig:291 msgid "Copy Screen to Temporary File and Paste Path" -msgstr "" +msgstr "Зберегти екран до файлу і вставити шлях" #: src/input/command.zig:292 msgid "" "Copy the screen contents to a temporary file and paste the path to the file." msgstr "" +"Зберегти вміст екрана до тимчасового файлу і вставити шлях до файлу." #: src/input/command.zig:296 msgid "Copy Screen to Temporary File and Open" -msgstr "" +msgstr "Зберегти екран до файлу і відкрити файл" #: src/input/command.zig:297 msgid "Copy the screen contents to a temporary file and open it." -msgstr "" +msgstr "Зберегти вміст екрана до тимчасового файлу і відкрити файл." #: src/input/command.zig:305 msgid "Copy Screen as HTML to Temporary File and Copy Path" -msgstr "" +msgstr "Зберегти екран у форматі HTML до файлу і скопіювати шлях" #: src/input/command.zig:306 msgid "" "Copy the screen contents as HTML to a temporary file and copy the path to " "the clipboard." msgstr "" +"Зберегти вміст екрана у форматі HTML до тимчасового файлу і скопіювати шлях " +"до файлу до буфера обміну." #: src/input/command.zig:313 msgid "Copy Screen as HTML to Temporary File and Paste Path" -msgstr "" +msgstr "Зберегти екран у форматі HTML до файлу і вставити шлях" #: src/input/command.zig:314 msgid "" "Copy the screen contents as HTML to a temporary file and paste the path to " "the file." msgstr "" +"Зберегти вміст екрана у форматі HTML до тимчасового файлу і вставити шлях до " +"файлу." #: src/input/command.zig:321 msgid "Copy Screen as HTML to Temporary File and Open" -msgstr "" +msgstr "Зберегти екран у форматі HTML до файлу і відкрити файл" #: src/input/command.zig:322 msgid "Copy the screen contents as HTML to a temporary file and open it." msgstr "" +"Зберегти вміст екрана у форматі HTML до тимчасового файлу і відкрити файл." #: src/input/command.zig:330 msgid "Copy Screen as ANSI Sequences to Temporary File and Copy Path" -msgstr "" +msgstr "Зберегти екран як ANSI-послідовності до файлу і скопіювати шлях" #: src/input/command.zig:331 msgid "" "Copy the screen contents as ANSI escape sequences to a temporary file and " "copy the path to the clipboard." msgstr "" +"Зберегти вміст екрана як ANSI-послідовності до тимчасового файлу і " +"скопіювати шлях до файлу до буфера обміну." #: src/input/command.zig:338 msgid "Copy Screen as ANSI Sequences to Temporary File and Paste Path" -msgstr "" +msgstr "Зберегти екран як ANSI-послідовності до файлу і вставити шлях" #: src/input/command.zig:339 msgid "" "Copy the screen contents as ANSI escape sequences to a temporary file and " "paste the path to the file." msgstr "" +"Зберегти вміст екрана як ANSI-послідовності до тимчасового файлу і вставити " +"шлях до файлу." #: src/input/command.zig:346 msgid "Copy Screen as ANSI Sequences to Temporary File and Open" -msgstr "" +msgstr "Зберегти екран як ANSI-послідовності до файлу і відкрити файл" #: src/input/command.zig:347 msgid "" "Copy the screen contents as ANSI escape sequences to a temporary file and " "open it." msgstr "" +"Зберегти вміст екрана як ANSI-послідовності до тимчасового файлу і відкрити " +"файл." #: src/input/command.zig:354 msgid "Copy Selection to Temporary File and Copy Path" -msgstr "" +msgstr "Зберегти виділене до файлу і скопіювати шлях" #: src/input/command.zig:355 msgid "" "Copy the selection contents to a temporary file and copy the path to the " "clipboard." msgstr "" +"Зберегти виділене до тимчасового файлу і скопіювати шлях до файлу до буфера " +"обміну." #: src/input/command.zig:359 msgid "Copy Selection to Temporary File and Paste Path" -msgstr "" +msgstr "Зберегти виділене до файлу і вставити шлях" #: src/input/command.zig:360 msgid "" "Copy the selection contents to a temporary file and paste the path to the " "file." -msgstr "" +msgstr "Зберегти виділене до тимчасового файлу і вставити шлях до файлу." #: src/input/command.zig:364 msgid "Copy Selection to Temporary File and Open" -msgstr "" +msgstr "Зберегти виділене до файлу і відкрити файл" #: src/input/command.zig:365 msgid "Copy the selection contents to a temporary file and open it." -msgstr "" +msgstr "Зберегти виділене до тимчасового файлу і відкрити файл." #: src/input/command.zig:373 msgid "Copy Selection as HTML to Temporary File and Copy Path" -msgstr "" +msgstr "Зберегти виділене у форматі HTML до файлу і скопіювати шлях" #: src/input/command.zig:374 msgid "" "Copy the selection contents as HTML to a temporary file and copy the path to " "the clipboard." msgstr "" +"Зберегти виділене у форматі HTML до тимчасового файлу і скопіювати шлях до " +"файлу до буфера обміну." #: src/input/command.zig:381 msgid "Copy Selection as HTML to Temporary File and Paste Path" -msgstr "" +msgstr "Зберегти виділене у форматі HTML до файлу і вставити шлях" #: src/input/command.zig:382 msgid "" "Copy the selection contents as HTML to a temporary file and paste the path " "to the file." msgstr "" +"Зберегти виділене у форматі HTML до тимчасового файлу і вставити шлях до " +"файлу." #: src/input/command.zig:389 msgid "Copy Selection as HTML to Temporary File and Open" -msgstr "" +msgstr "Зберегти виділене у форматі HTML до файлу і відкрити файл" #: src/input/command.zig:390 msgid "Copy the selection contents as HTML to a temporary file and open it." -msgstr "" +msgstr "Зберегти виділене у форматі HTML до тимчасового файлу і відкрити файл." #: src/input/command.zig:398 msgid "Copy Selection as ANSI Sequences to Temporary File and Copy Path" -msgstr "" +msgstr "Зберегти виділене як ANSI-послідовності до файлу і скопіювати шлях" #: src/input/command.zig:399 msgid "" "Copy the selection contents as ANSI escape sequences to a temporary file and " "copy the path to the clipboard." msgstr "" +"Зберегти виділене як ANSI-послідовності до тимчасового файлу і скопіювати " +"шлях до файлу до буфера обміну." #: src/input/command.zig:406 msgid "Copy Selection as ANSI Sequences to Temporary File and Paste Path" -msgstr "" +msgstr "Зберегти виділене як ANSI-послідовності до файлу і вставити шлях" #: src/input/command.zig:407 msgid "" "Copy the selection contents as ANSI escape sequences to a temporary file and " "paste the path to the file." msgstr "" +"Зберегти виділене як ANSI-послідовності до тимчасового файлу і вставити шлях " +"до файлу." #: src/input/command.zig:414 msgid "Copy Selection as ANSI Sequences to Temporary File and Open" -msgstr "" +msgstr "Зберегти виділене як ANSI-послідовності до файлу і відкрити файл" #: src/input/command.zig:415 msgid "" "Copy the selection contents as ANSI escape sequences to a temporary file and " "open it." msgstr "" +"Зберегти виділене як ANSI-послідовності до тимчасового файлу і відкрити файл." #: src/input/command.zig:422 msgid "Open a new window." -msgstr "" +msgstr "Створити нове вікно." #: src/input/command.zig:428 msgid "Open a new tab." -msgstr "" +msgstr "Створити нову вкладку." #: src/input/command.zig:434 msgid "Move Tab Left" -msgstr "" +msgstr "Пересунути вкладку ліворуч" #: src/input/command.zig:435 msgid "Move the current tab to the left." -msgstr "" +msgstr "Пересунути поточну вкладку ліворуч." #: src/input/command.zig:439 msgid "Move Tab Right" -msgstr "" +msgstr "Пересунути вкладку праворуч" #: src/input/command.zig:440 msgid "Move the current tab to the right." -msgstr "" +msgstr "Пересунути поточну вкладку праворуч." #: src/input/command.zig:446 msgid "Move Tab to New Window" -msgstr "" +msgstr "Винести вкладку до нового вікна" #: src/input/command.zig:447 msgid "Move the current tab to a new window." -msgstr "" +msgstr "Винести поточну вкладку до нового вікна." #: src/input/command.zig:452 msgid "Toggle Tab Overview" -msgstr "" +msgstr "Перемкнути огляд вкладок" #: src/input/command.zig:453 msgid "Toggle the tab overview." -msgstr "" +msgstr "Перемкнути огляд вкладок." #: src/input/command.zig:458 msgid "Change Terminal Title…" -msgstr "" +msgstr "Змінити заголовок терміналу…" #: src/input/command.zig:459 msgid "Prompt for a new title for the current terminal." -msgstr "" +msgstr "Спитати новий заголовок для поточного терміналу." #: src/input/command.zig:465 msgid "Prompt for a new title for the current tab." -msgstr "" +msgstr "Спитати новий заголовок для поточної вкладки." #: src/input/command.zig:478 msgid "Split the terminal to the left." -msgstr "" +msgstr "Створити нову панель ліворуч." #: src/input/command.zig:483 msgid "Split the terminal to the right." -msgstr "" +msgstr "Створити нову панель праворуч." #: src/input/command.zig:488 msgid "Split the terminal up." -msgstr "" +msgstr "Створити нову панель зверху." #: src/input/command.zig:493 msgid "Split the terminal down." -msgstr "" +msgstr "Створити нову панель знизу." #: src/input/command.zig:500 msgid "Focus Split: Previous" -msgstr "" +msgstr "Перейти до попередньої панелі" #: src/input/command.zig:501 msgid "Focus the previous split, if any." -msgstr "" +msgstr "Перейти до попередньої панелі, якщо така є." #: src/input/command.zig:505 msgid "Focus Split: Next" -msgstr "" +msgstr "Перейти до наступної панелі" #: src/input/command.zig:506 msgid "Focus the next split, if any." -msgstr "" +msgstr "Перейти до наступної панелі, якщо така є." #: src/input/command.zig:510 msgid "Focus Split: Left" -msgstr "" +msgstr "Перейти до панелі ліворуч" #: src/input/command.zig:511 msgid "Focus the split to the left, if it exists." -msgstr "" +msgstr "Перейти до панелі ліворуч, якщо така є." #: src/input/command.zig:515 msgid "Focus Split: Right" -msgstr "" +msgstr "Перейти до панелі праворуч" #: src/input/command.zig:516 msgid "Focus the split to the right, if it exists." -msgstr "" +msgstr "Перейти до панелі праворуч, якщо така є." #: src/input/command.zig:520 msgid "Focus Split: Up" -msgstr "" +msgstr "Перейти до панелі зверху" #: src/input/command.zig:521 msgid "Focus the split above, if it exists." -msgstr "" +msgstr "Перейти до панелі зверху, якщо така є." #: src/input/command.zig:525 msgid "Focus Split: Down" -msgstr "" +msgstr "Перейти до панелі знизу" #: src/input/command.zig:526 msgid "Focus the split below, if it exists." -msgstr "" +msgstr "Перейти до панелі знизу, якщо така є." #: src/input/command.zig:533 msgid "Focus Window: Previous" -msgstr "" +msgstr "Перейти до попереднього вікна" #: src/input/command.zig:534 msgid "Focus the previous window, if any." -msgstr "" +msgstr "Перейти до попереднього вікна, якщо таке є." #: src/input/command.zig:538 msgid "Focus Window: Next" -msgstr "" +msgstr "Перейти до наступного вікна" #: src/input/command.zig:539 msgid "Focus the next window, if any." -msgstr "" +msgstr "Перейти до наступного вікна, якщо таке є." #: src/input/command.zig:545 msgid "Toggle Split Zoom" -msgstr "" +msgstr "Перемкнути масштабування панелі" #: src/input/command.zig:546 msgid "Toggle the zoom state of the current split." -msgstr "" +msgstr "Перемкнути режим масштабування поточної панелі." #: src/input/command.zig:551 msgid "Toggle Read-Only Mode" -msgstr "" +msgstr "Перемкнути режим «лише читання»" #: src/input/command.zig:552 msgid "Toggle read-only mode for the current surface." -msgstr "" +msgstr "Перемкнути режим «лише читання» для поточної панелі." #: src/input/command.zig:557 msgid "Equalize Splits" -msgstr "" +msgstr "Вирівняти панелі" #: src/input/command.zig:558 msgid "Equalize the size of all splits." -msgstr "" +msgstr "Вирівняти розміри всіх панелей." #: src/input/command.zig:563 msgid "Reset Window Size" -msgstr "" +msgstr "Скинути розмір вікна" #: src/input/command.zig:564 msgid "Reset the window size to the default." -msgstr "" +msgstr "Скинути розмір вікна до значення за замовчуванням." #: src/input/command.zig:569 msgid "Toggle Inspector" -msgstr "" +msgstr "Перемкнути термінальний інспектор" #: src/input/command.zig:570 msgid "Toggle the inspector." -msgstr "" +msgstr "Перемкнути термінальний інспектор." #: src/input/command.zig:575 msgid "Show the GTK Inspector" -msgstr "" +msgstr "Показати інспектор GTK" #: src/input/command.zig:576 msgid "Show the GTK inspector." -msgstr "" +msgstr "Показати інспектор GTK." #: src/input/command.zig:581 msgid "Show On-Screen Keyboard" -msgstr "" +msgstr "Показати екранну клавіатуру" #: src/input/command.zig:582 msgid "Show the on-screen keyboard if present." -msgstr "" +msgstr "Показати екранну клавіатуру, якщо така є." #: src/input/command.zig:588 msgid "Open Config Using OS editor" -msgstr "" +msgstr "Відкрити налаштування в системному редакторі" #: src/input/command.zig:589 msgid "Open the config file with the OS's default editor." -msgstr "" +msgstr "Відкрити файл налаштувань у системному редакторі за замовчуванням." #: src/input/command.zig:593 msgid "Open Config in New Terminal Window" -msgstr "" +msgstr "Відкрити налаштування в новому вікні" #: src/input/command.zig:594 msgid "Open the config file in a new window using $EDITOR or $VISUAL." msgstr "" +"Відкрити файл налаштувань в новому вікні за допомогою $EDITOR або $VISUAL." #: src/input/command.zig:600 msgid "Reload Config" -msgstr "" +msgstr "Перезавантажити налаштування" #: src/input/command.zig:601 msgid "Reload the config file." -msgstr "" +msgstr "Перезавантажити файл налаштувань." #: src/input/command.zig:606 msgid "Close Terminal" -msgstr "" +msgstr "Закрити термінал" #: src/input/command.zig:607 msgid "Close the current terminal." -msgstr "" +msgstr "Закрити поточний термінал." #: src/input/command.zig:614 msgid "Close the current tab." -msgstr "" +msgstr "Закрити поточну вкладку." #: src/input/command.zig:618 msgid "Close Other Tabs" -msgstr "" +msgstr "Закрити інші вкладки" #: src/input/command.zig:619 msgid "Close all tabs in this window except the current one." -msgstr "" +msgstr "Закрити всі вкладки в цьому вікні, окрім поточної." #: src/input/command.zig:623 msgid "Close Tabs to the Right" -msgstr "" +msgstr "Закрити вкладки праворуч" #: src/input/command.zig:624 msgid "Close all tabs to the right of the current one." -msgstr "" +msgstr "Закрити всі вкладки праворуч поточної." #: src/input/command.zig:631 msgid "Close the current window." -msgstr "" +msgstr "Закрити поточне вікно." #: src/input/command.zig:636 msgid "Close All Windows" -msgstr "" +msgstr "Закрити всі вікна" #: src/input/command.zig:637 msgid "Close all windows." -msgstr "" +msgstr "Закрити всі вікна." #: src/input/command.zig:642 msgid "Toggle Maximize" -msgstr "" +msgstr "Перемкнути розгортання" #: src/input/command.zig:643 msgid "Toggle the maximized state of the current window." -msgstr "" +msgstr "Перемкнути розгортання поточного вікна." #: src/input/command.zig:648 msgid "Toggle Fullscreen" -msgstr "" +msgstr "Перемкнути повноекранний режим" #: src/input/command.zig:649 msgid "Toggle the fullscreen state of the current window." -msgstr "" +msgstr "Перемкнути повноекранний режим поточного вікна." #: src/input/command.zig:654 msgid "Toggle Window Decorations" -msgstr "" +msgstr "Перемкнути оформлення вікон" #: src/input/command.zig:655 msgid "Toggle the window decorations." -msgstr "" +msgstr "Перемкнути оформлення вікон." #: src/input/command.zig:660 msgid "Toggle Float on Top" -msgstr "" +msgstr "Перемкнути режим «поверх інших вікон»" #: src/input/command.zig:661 msgid "Toggle the float on top state of the current window." -msgstr "" +msgstr "Перемкнути режим «поверх інших вікон» для поточного вікна." #: src/input/command.zig:666 msgid "Toggle Secure Input" -msgstr "" +msgstr "Перемкнути безпечне введення" #: src/input/command.zig:667 msgid "Toggle secure input mode." -msgstr "" +msgstr "Перемкнути режим безпечного введення." #: src/input/command.zig:672 msgid "Toggle Mouse Reporting" -msgstr "" +msgstr "Перемкнути передавання подій миші" #: src/input/command.zig:673 msgid "Toggle whether mouse events are reported to terminal applications." -msgstr "" +msgstr "Перемкнути передавання подій миші до термінальних застосунків." #: src/input/command.zig:678 msgid "Toggle Background Opacity" -msgstr "" +msgstr "Перемкнути непрозорість фону" #: src/input/command.zig:679 msgid "Toggle the background opacity of a window that started transparent." msgstr "" +"Перемкнути непрозорість фону вікна, фон якого спочатку був прозорим." #: src/input/command.zig:684 msgid "Check for Updates" -msgstr "" +msgstr "Перевірити наявність оновлень" #: src/input/command.zig:685 msgid "Check for updates to the application." -msgstr "" +msgstr "Перевірити наявність оновлень застосунку." #: src/input/command.zig:690 msgid "Undo" -msgstr "" +msgstr "Скасувати" #: src/input/command.zig:691 msgid "Undo the last action." -msgstr "" +msgstr "Скасувати останню дію." #: src/input/command.zig:696 msgid "Redo" -msgstr "" +msgstr "Повторити" #: src/input/command.zig:697 msgid "Redo the last undone action." -msgstr "" +msgstr "Повторити останню скасовану дію." #: src/input/command.zig:703 msgid "Quit the application." -msgstr "" +msgstr "Вийти із застосунку." #: src/input/command.zig:708 msgid "Ghostty" -msgstr "" +msgstr "Привиденя" #: src/input/command.zig:709 msgid "Put a little Ghostty in your terminal." -msgstr "" +msgstr "Вставити маленького привида у ваш термінал." From c50288c35fd147482dbd7e30cfcc414c7612c7dd Mon Sep 17 00:00:00 2001 From: Volodymyr Chernetskyi <19735328+chernetskyi@users.noreply.github.com> Date: Mon, 17 Aug 2026 08:00:13 +0200 Subject: [PATCH 02/21] i18n: address comments for Ukrainian translation --- po/uk.po | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/po/uk.po b/po/uk.po index 901a02104..d413b2d18 100644 --- a/po/uk.po +++ b/po/uk.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: com.mitchellh.ghostty\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n" "POT-Creation-Date: 2026-08-10 10:06-0500\n" -"PO-Revision-Date: 2026-08-16 09:02+0100\n" +"PO-Revision-Date: 2026-08-17 08:00+0100\n" "Last-Translator: Volodymyr Chernetskyi " "<19735328+chernetskyi@users.noreply.github.com>\n" "Language-Team: Ukrainian \n" @@ -70,7 +70,7 @@ msgid "" "and either reload your configuration or ignore these errors." msgstr "" "Виявлено одну або кілька помилок налаштування. Будь ласка, перегляньте " -"помилки нижче і перезавантажте налаштування або проігноруйте ці помилки." +"помилки нижче та перезавантажте налаштування або проігноруйте ці помилки." #: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:12 msgid "Ignore" @@ -118,7 +118,7 @@ msgid "" "through the content, but no input events will be sent to the running " "application." msgstr "" -"Цей термінал працює в режимі «лише читання». Можна переглядати, виділяти і " +"Цей термінал працює в режимі «лише читання». Можна переглядати, виділяти та " "прокручувати вміст, але події введення не передаватимуться до запущеної " "програми." @@ -1129,7 +1129,7 @@ msgstr "Вийти із застосунку." #: src/input/command.zig:708 msgid "Ghostty" -msgstr "Привиденя" +msgstr "Маленький привид" #: src/input/command.zig:709 msgid "Put a little Ghostty in your terminal." From 2a51bdf1266df638e9ba49ad5cfad6ee7c780ca3 Mon Sep 17 00:00:00 2001 From: Volodymyr Chernetskyi <19735328+chernetskyi@users.noreply.github.com> Date: Tue, 18 Aug 2026 21:23:04 +0200 Subject: [PATCH 03/21] i18n: return Ghostty to Ukrainian translation --- po/uk.po | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/po/uk.po b/po/uk.po index d413b2d18..f0cf9f79c 100644 --- a/po/uk.po +++ b/po/uk.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: com.mitchellh.ghostty\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n" "POT-Creation-Date: 2026-08-10 10:06-0500\n" -"PO-Revision-Date: 2026-08-17 08:00+0100\n" +"PO-Revision-Date: 2026-08-18 21:23+0100\n" "Last-Translator: Volodymyr Chernetskyi " "<19735328+chernetskyi@users.noreply.github.com>\n" "Language-Team: Ukrainian \n" @@ -1129,8 +1129,8 @@ msgstr "Вийти із застосунку." #: src/input/command.zig:708 msgid "Ghostty" -msgstr "Маленький привид" +msgstr "Привид Ghostty" #: src/input/command.zig:709 msgid "Put a little Ghostty in your terminal." -msgstr "Вставити маленького привида у ваш термінал." +msgstr "Вставити маленького Ghostty у ваш термінал." From 1026a00c19b3cbf254c0b85dced92ab8e63d77bf Mon Sep 17 00:00:00 2001 From: Volodymyr Chernetskyi <19735328+chernetskyi@users.noreply.github.com> Date: Wed, 19 Aug 2026 19:34:05 +0200 Subject: [PATCH 04/21] i18n: adjust Ukrainian translations --- po/uk.po | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/po/uk.po b/po/uk.po index f0cf9f79c..f1efb115e 100644 --- a/po/uk.po +++ b/po/uk.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: com.mitchellh.ghostty\n" "Report-Msgid-Bugs-To: m@mitchellh.com\n" "POT-Creation-Date: 2026-08-10 10:06-0500\n" -"PO-Revision-Date: 2026-08-18 21:23+0100\n" +"PO-Revision-Date: 2026-08-19 19:34+0100\n" "Last-Translator: Volodymyr Chernetskyi " "<19735328+chernetskyi@users.noreply.github.com>\n" "Language-Team: Ukrainian \n" @@ -69,7 +69,7 @@ msgid "" "One or more configuration errors were found. Please review the errors below, " "and either reload your configuration or ignore these errors." msgstr "" -"Виявлено одну або кілька помилок налаштування. Будь ласка, перегляньте " +"Виявлено одну або декілька помилок налаштування. Будь ласка, перегляньте " "помилки нижче та перезавантажте налаштування або проігноруйте ці помилки." #: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:12 @@ -270,11 +270,11 @@ msgstr "Виконати команду…" #: src/apprt/gtk/class/application.zig:1767 msgid "The keybind was revoked by the system." -msgstr "Привʼязка клавіш відкликана системою." +msgstr "Дана привʼязка клавіш відкликана системою." #: src/apprt/gtk/class/application.zig:1769 msgid "The keybind was denied by the system." -msgstr "Привʼязка клавіш відхилена системою." +msgstr "Дана привʼязка клавіш відхилена системою." #: src/apprt/gtk/class/application.zig:1780 msgid "Global keybind unavailable" @@ -318,7 +318,7 @@ msgid "" "commands may be executed." msgstr "" "Вставка цього тексту в термінал може бути небезпечною, оскільки, схоже, " -"деякі команди можуть бути виконані." +"можуть бути виконані деякі команди." #: src/apprt/gtk/class/close_confirmation_dialog.zig:184 msgid "Quit Ghostty?" From 6cd684d5d3b2a83c9966b6c5ba239d36fbd937a9 Mon Sep 17 00:00:00 2001 From: Daniel Kinzler Date: Fri, 28 Aug 2026 14:25:33 +0200 Subject: [PATCH 05/21] gtk: fix stale pointers to property bindings Previously, the property binding created in `Surface.bindIsSplit` would get freed automatically when the source object (the SplitTree widget) got finalized. A subsequent call to `bindIsSplit` could then cause a crash by using the stale pointer to the binding. This bug could e.g. be triggered by dragging the surface from a single-surface tab to another tab. We now create an extra reference to the binding object so that Surface essentially owns the binding and is responsible for freeing it. Updated the binding in `SurfaceScrolledWindow` to use the same pattern. That one was probably fine, because the binding is only created once, but let's be safe. --- src/apprt/gtk/class/surface.zig | 20 +++++++++++++++++-- .../gtk/class/surface_scrolled_window.zig | 12 ++++++++--- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/apprt/gtk/class/surface.zig b/src/apprt/gtk/class/surface.zig index e6cfe5c50..59d8ed0f7 100644 --- a/src/apprt/gtk/class/surface.zig +++ b/src/apprt/gtk/class/surface.zig @@ -853,14 +853,24 @@ pub const Surface = extern struct { pub fn bindIsSplit(self: *Self, tree: *SplitTree) void { const priv = self.private(); - if (priv.is_split_binding) |bind| bind.unbind(); + if (priv.is_split_binding) |binding| { + binding.unbind(); + binding.unref(); + priv.is_split_binding = null; + } - priv.is_split_binding = tree.as(gobject.Object).bindProperty( + const binding = tree.as(gobject.Object).bindProperty( "is-split", self.as(gobject.Object), "is-split", .{ .sync_create = true }, ); + // The ref created by bindProperty is owned by the binding itself. + // We need another ref to prevent the binding object from being + // freed if the source object (SplitTree) is finalized. Otherwise + // our pointer to the binding could become stale. + binding.ref(); + priv.is_split_binding = binding; } /// Callback used to determine whether unfocused-split-fill / unfocused-split-opacity @@ -1881,6 +1891,12 @@ pub const Surface = extern struct { priv.config = null; } + if (priv.is_split_binding) |binding| { + binding.unbind(); + binding.unref(); + priv.is_split_binding = null; + } + if (priv.vadj_signal_group) |group| { group.setTarget(null); group.as(gobject.Object).unref(); diff --git a/src/apprt/gtk/class/surface_scrolled_window.zig b/src/apprt/gtk/class/surface_scrolled_window.zig index 6ccb0a0d2..ad9a4cc7e 100644 --- a/src/apprt/gtk/class/surface_scrolled_window.zig +++ b/src/apprt/gtk/class/surface_scrolled_window.zig @@ -89,7 +89,8 @@ pub const SurfaceScrolledWindow = extern struct { const priv = self.private(); if (priv.config_binding) |binding| { - binding.as(gobject.Object).unref(); + binding.unbind(); + binding.unref(); priv.config_binding = null; } @@ -168,18 +169,23 @@ pub const SurfaceScrolledWindow = extern struct { // Unbind old config binding if it exists if (priv.config_binding) |binding| { - binding.as(gobject.Object).unref(); + binding.unbind(); + binding.unref(); priv.config_binding = null; } // Bind config from surface to our config property if (priv.surface) |surface| { - priv.config_binding = surface.as(gobject.Object).bindProperty( + const binding = surface.as(gobject.Object).bindProperty( properties.config.name, self.as(gobject.Object), properties.config.name, .{ .sync_create = true }, ); + // Keep another ref, otherwise the binding would be freed and + // our pointer become stale if the surface gets finalized. + binding.ref(); + priv.config_binding = binding; } } From 97f57edccc10cb5ccef34d9d4c94276748bbd953 Mon Sep 17 00:00:00 2001 From: Jesse Miller Date: Sat, 29 Aug 2026 08:14:36 -0600 Subject: [PATCH 06/21] renderer: vsync unfocused surfaces while dirty 6ae1784f4 Unfocused surfaces stopped the CVDisplayLink and encoded a GPU frame on every PTY wakeup. A burst of close writes became that many Metal submits instead of one vsync. Keep the link running while the surface is visible and dirty or animating, whether or not it is focused. Idle surfaces still park. Focus continues to gate cursor blink, custom-shader animation, and QoS. --- src/renderer/generic.zig | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/renderer/generic.zig b/src/renderer/generic.zig index 2c9fb1093..2a81f42b4 100644 --- a/src/renderer/generic.zig +++ b/src/renderer/generic.zig @@ -1194,8 +1194,6 @@ pub fn Renderer(comptime GraphicsAPI: type) type { const should_run = // Non-visible windows never vsync self.visible and - // Non-focused windows only render on-demand - self.focused and // Only vsync if we have cell changes or animation (self.cells_rebuilt or self.animationWake() != null); From caf48a41ee5c3861c786270d64bac950f2513012 Mon Sep 17 00:00:00 2001 From: "Jeffrey C. Ollie" Date: Sat, 29 Aug 2026 09:20:11 -0500 Subject: [PATCH 07/21] main: fix inverted allow_stack_tracing condition The Zig 0.16.0 update dropped the negation from the std default (!strip_debug_info), disabling stack traces in every unstripped build. AI disclosure: Claude Fable was used to diagnose the problem and find the fix. Commit message was written by me. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01QfzQME46DQXwMWa43bQaa3 --- src/main_ghostty.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main_ghostty.zig b/src/main_ghostty.zig index 86e779899..f4fa74133 100644 --- a/src/main_ghostty.zig +++ b/src/main_ghostty.zig @@ -228,7 +228,7 @@ pub const std_options: std.Options = .{ .allow_stack_tracing = if (builtin.target.os.tag.isDarwin() and builtin.target.os.tag != .macos) false else - builtin.strip_debug_info, + !builtin.strip_debug_info, }; test { From 166d2fe34d65bd1fa393fd8a213c57bc6119dfb9 Mon Sep 17 00:00:00 2001 From: svector-anu Date: Sat, 29 Aug 2026 16:17:24 +0100 Subject: [PATCH 08/21] build: update Sparkle to 2.9.4 --- .github/workflows/release-tag.yml | 4 ++-- .github/workflows/release-tip.yml | 6 +++--- .../xcshareddata/swiftpm/Package.resolved | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release-tag.yml b/.github/workflows/release-tag.yml index f7b076bf0..60a2e80e9 100644 --- a/.github/workflows/release-tag.yml +++ b/.github/workflows/release-tag.yml @@ -160,7 +160,7 @@ jobs: - name: Setup Sparkle env: - SPARKLE_VERSION: 2.9.0 + SPARKLE_VERSION: 2.9.4 run: | mkdir -p .action/sparkle cd .action/sparkle @@ -328,7 +328,7 @@ jobs: - name: Setup Sparkle env: - SPARKLE_VERSION: 2.9.0 + SPARKLE_VERSION: 2.9.4 run: | mkdir -p .action/sparkle cd .action/sparkle diff --git a/.github/workflows/release-tip.yml b/.github/workflows/release-tip.yml index 5cda284bb..d4e6b7162 100644 --- a/.github/workflows/release-tip.yml +++ b/.github/workflows/release-tip.yml @@ -591,7 +591,7 @@ jobs: # Setup Sparkle - name: Setup Sparkle env: - SPARKLE_VERSION: 2.9.0 + SPARKLE_VERSION: 2.9.4 run: | mkdir -p .action/sparkle cd .action/sparkle @@ -847,7 +847,7 @@ jobs: # Setup Sparkle - name: Setup Sparkle env: - SPARKLE_VERSION: 2.9.0 + SPARKLE_VERSION: 2.9.4 run: | mkdir -p .action/sparkle cd .action/sparkle @@ -1044,7 +1044,7 @@ jobs: # Setup Sparkle - name: Setup Sparkle env: - SPARKLE_VERSION: 2.9.0 + SPARKLE_VERSION: 2.9.4 run: | mkdir -p .action/sparkle cd .action/sparkle diff --git a/macos/Ghostty.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/macos/Ghostty.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 6e450d9bc..feb7b4ba0 100644 --- a/macos/Ghostty.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/macos/Ghostty.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -6,8 +6,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/sparkle-project/Sparkle", "state" : { - "revision" : "21d8df80440b1ca3b65fa82e40782f1e5a9e6ba2", - "version" : "2.9.0" + "revision" : "b6496a74a087257ef5e6da1c5b29a447a60f5bd7", + "version" : "2.9.4" } } ], From 7b47213f94058c3715205ce8fa73f7ae581a652c Mon Sep 17 00:00:00 2001 From: "ghostty-vouch[bot]" <262049992+ghostty-vouch[bot]@users.noreply.github.com> Date: Sat, 29 Aug 2026 15:59:43 +0000 Subject: [PATCH 09/21] Update VOUCHED list (#14074) Triggered by [comment](https://github.com/ghostty-org/ghostty/issues/14072#issuecomment-5463405035) from @bo2themax. Vouch: @Svector-anu Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .github/VOUCHED.td | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/VOUCHED.td b/.github/VOUCHED.td index b6ff45196..423517a15 100644 --- a/.github/VOUCHED.td +++ b/.github/VOUCHED.td @@ -301,6 +301,7 @@ simonbcn slsrepo steven-tk sunshine-syz +svector-anu svmhdvn tacherasasi -tangivis From 094d175efa506f87c296fd8a51371c68eea191b9 Mon Sep 17 00:00:00 2001 From: mitchellh <1299+mitchellh@users.noreply.github.com> Date: Sun, 30 Aug 2026 00:22:34 +0000 Subject: [PATCH 10/21] deps: Update iTerm2 color schemes --- build.zig.zon | 4 ++-- build.zig.zon.json | 6 +++--- build.zig.zon.nix | 6 +++--- build.zig.zon.txt | 2 +- flatpak/zig-packages.json | 6 +++--- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/build.zig.zon b/build.zig.zon index 96cda01a0..e30650519 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -125,8 +125,8 @@ .apple_sdk = .{ .path = "./pkg/apple-sdk" }, .android_ndk = .{ .path = "./pkg/android-ndk" }, .iterm2_themes = .{ - .url = "https://deps.files.ghostty.org/ghostty-themes-release-20260810-152212-0173c3c.tgz", - .hash = "N-V-__8AAPpcBAD4_75xLBbLiYqdojOwQP74eoWmpL3jPrBl", + .url = "https://deps.files.ghostty.org/ghostty-themes-release-20260824-153547-75c93ee.tgz", + .hash = "N-V-__8AAGZkBACH0haGC9R-hfNPYWxu16hr-ydEsolad9GV", .lazy = true, }, }, diff --git a/build.zig.zon.json b/build.zig.zon.json index 376ca05cb..e3d3b205a 100644 --- a/build.zig.zon.json +++ b/build.zig.zon.json @@ -59,10 +59,10 @@ "url": "https://deps.files.ghostty.org/N-V-__8AAEbOfQBnvcFcCX2W5z7tDaN8vaNZGamEQtNOe0UI.tar.gz", "hash": "sha256-yBbCDox18+Fa6Gc1DnmSVQLRpqhZOLsac7iSfl8x+cs=" }, - "N-V-__8AAPpcBAD4_75xLBbLiYqdojOwQP74eoWmpL3jPrBl": { + "N-V-__8AAGZkBACH0haGC9R-hfNPYWxu16hr-ydEsolad9GV": { "name": "iterm2_themes", - "url": "https://deps.files.ghostty.org/ghostty-themes-release-20260810-152212-0173c3c.tgz", - "hash": "sha256-6ph4RxQg7lsS5/L/SACZyVTqUOVzob34P0PhBcm+Y/A=" + "url": "https://deps.files.ghostty.org/ghostty-themes-release-20260824-153547-75c93ee.tgz", + "hash": "sha256-sf0fMQV/l8EnTbA8bORJYIN6GkH1InXLxkruLm40654=" }, "N-V-__8AAIC5lwAVPJJzxnCAahSvZTIlG-HhtOvnM1uh-66x": { "name": "jetbrains_mono", diff --git a/build.zig.zon.nix b/build.zig.zon.nix index e955d4dc4..58ce3fda6 100644 --- a/build.zig.zon.nix +++ b/build.zig.zon.nix @@ -206,11 +206,11 @@ in }; } { - name = "N-V-__8AAPpcBAD4_75xLBbLiYqdojOwQP74eoWmpL3jPrBl"; + name = "N-V-__8AAGZkBACH0haGC9R-hfNPYWxu16hr-ydEsolad9GV"; path = fetchZigArtifact { name = "iterm2_themes"; - url = "https://deps.files.ghostty.org/ghostty-themes-release-20260810-152212-0173c3c.tgz"; - hash = "sha256-6ph4RxQg7lsS5/L/SACZyVTqUOVzob34P0PhBcm+Y/A="; + url = "https://deps.files.ghostty.org/ghostty-themes-release-20260824-153547-75c93ee.tgz"; + hash = "sha256-sf0fMQV/l8EnTbA8bORJYIN6GkH1InXLxkruLm40654="; unpack = false; }; } diff --git a/build.zig.zon.txt b/build.zig.zon.txt index 82e00bd4b..77df51c0b 100644 --- a/build.zig.zon.txt +++ b/build.zig.zon.txt @@ -9,7 +9,7 @@ https://deps.files.ghostty.org/breakpad-b99f444ba5f6b98cac261cbb391d8766b34a5918 https://deps.files.ghostty.org/fontconfig-2.14.2.tar.gz https://deps.files.ghostty.org/freetype-1220b81f6ecfb3fd222f76cf9106fecfa6554ab07ec7fdc4124b9bb063ae2adf969d.tar.gz https://deps.files.ghostty.org/gettext-0.24.tar.gz -https://deps.files.ghostty.org/ghostty-themes-release-20260810-152212-0173c3c.tgz +https://deps.files.ghostty.org/ghostty-themes-release-20260824-153547-75c93ee.tgz https://deps.files.ghostty.org/glslang-12201278a1a05c0ce0b6eb6026c65cd3e9247aa041b1c260324bf29cee559dd23ba1.tar.gz https://deps.files.ghostty.org/gobject-2026-07-28-36-1.tar.zst https://deps.files.ghostty.org/gtk4-layer-shell-1.1.0.tar.gz diff --git a/flatpak/zig-packages.json b/flatpak/zig-packages.json index ad54aa752..4c9fb5cf8 100644 --- a/flatpak/zig-packages.json +++ b/flatpak/zig-packages.json @@ -73,9 +73,9 @@ }, { "type": "archive", - "url": "https://deps.files.ghostty.org/ghostty-themes-release-20260810-152212-0173c3c.tgz", - "dest": "vendor/p/N-V-__8AAPpcBAD4_75xLBbLiYqdojOwQP74eoWmpL3jPrBl", - "sha256": "ea9878471420ee5b12e7f2ff480099c954ea50e573a1bdf83f43e105c9be63f0" + "url": "https://deps.files.ghostty.org/ghostty-themes-release-20260824-153547-75c93ee.tgz", + "dest": "vendor/p/N-V-__8AAGZkBACH0haGC9R-hfNPYWxu16hr-ydEsolad9GV", + "sha256": "b1fd1f31057f97c1274db03c6ce44960837a1a41f52275cbc64aee2e6e34eb9e" }, { "type": "archive", From 98cd670c0c2ccdd3f22c40c65a3306e933643ada Mon Sep 17 00:00:00 2001 From: "ghostty-vouch[bot]" <262049992+ghostty-vouch[bot]@users.noreply.github.com> Date: Sun, 30 Aug 2026 02:40:12 +0000 Subject: [PATCH 11/21] Update VOUCHED list (#14079) Triggered by [discussion comment](https://github.com/ghostty-org/ghostty/discussions/14078#discussioncomment-18203195) from @jcollie. Vouch: @and-rs Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .github/VOUCHED.td | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/VOUCHED.td b/.github/VOUCHED.td index 423517a15..387df2f1c 100644 --- a/.github/VOUCHED.td +++ b/.github/VOUCHED.td @@ -46,6 +46,7 @@ alexfeijoo44 alexjuca alosarjos amadeus +and-rs andrejdaskalov anhthang anmitalidev From 090fca451d2c63bc2a5ccec23ea54cedce62c6a6 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 29 Aug 2026 19:53:11 -0700 Subject: [PATCH 12/21] terminal/kitty: validate POSIX shared memory names Update shared memory name validation according to the new spec: https://github.com/kovidgoyal/kitty/commit/22042970cf3a4668d02a1a7bcccca778ec864c21 --- src/terminal/kitty/graphics_image.zig | 66 +++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/src/terminal/kitty/graphics_image.zig b/src/terminal/kitty/graphics_image.zig index 489b672e3..945a127db 100644 --- a/src/terminal/kitty/graphics_image.zig +++ b/src/terminal/kitty/graphics_image.zig @@ -210,6 +210,15 @@ pub const LoadingImage = struct { return error.UnsupportedMedium; } + // POSIX shared memory names must begin with a slash, contain at + // least one character after it, contain no other slashes, and fit + // within NAME_MAX. Some shm_open implementations accept names + // without the leading slash, but the Kitty protocol does not. + if (!validSharedMemoryName(path, posix.NAME_MAX)) { + log.warn("invalid shared memory name", .{}); + return error.InvalidData; + } + // Since we're only supporting posix then max_path_bytes should // be enough to stack allocate the path. var buf: [std.fs.max_path_bytes]u8 = undefined; @@ -831,6 +840,16 @@ pub const Rect = struct { } }; +/// Returns whether a name follows the POSIX shared memory name format. +fn validSharedMemoryName(name: []const u8, name_max: usize) bool { + if (name.len < 2 or name.len > name_max or name[0] != '/') return false; + for (name[1..]) |c| { + if (c == '/' or c == 0) return false; + } + + return true; +} + /// Returns true if `path` is `dir` or is contained within it, requiring a /// path-separator boundary so similarly prefixed directories do not match. fn isPathInDir(dir: []const u8, path: []const u8) bool { @@ -852,6 +871,53 @@ test "temporary file path must be inside directory" { try testing.expect(!isPathInDir("/custom/tmp", "/custom/tmp-suffix/tty-graphics-protocol-image.data")); } +test "shared memory names follow POSIX rules" { + const testing = std.testing; + + try testing.expect(validSharedMemoryName("/kitty", 8)); + try testing.expect(validSharedMemoryName("/1234567", 8)); + + try testing.expect(!validSharedMemoryName("", 8)); + try testing.expect(!validSharedMemoryName("/", 8)); + try testing.expect(!validSharedMemoryName("kitty", 8)); + try testing.expect(!validSharedMemoryName("/kitty/image", 16)); + try testing.expect(!validSharedMemoryName("/kitty\x00image", 16)); + try testing.expect(!validSharedMemoryName("/12345678", 8)); +} + +test "image load rejects invalid POSIX shared memory names" { + if (comptime builtin.abi.isAndroid() or + builtin.target.os.tag == .windows or + !builtin.link_libc) + { + return error.SkipZigTest; + } + + const testing = std.testing; + const alloc = testing.allocator; + + var cmd: command.Command = .{ + .control = .{ .transmit = .{ + .format = .rgb, + .medium = .shared_memory, + .width = 1, + .height = 1, + .image_id = 31, + } }, + .data = try alloc.dupe(u8, "kitty-without-leading-slash"), + }; + defer cmd.deinit(alloc); + + try testing.expectError( + error.InvalidData, + LoadingImage.init(testing.io, alloc, &cmd, .{ + .file = false, + .temporary_file = .disabled, + .shared_memory = true, + }), + ); +} + test "shared memory range with offset and size" { const testing = std.testing; From 5f5495826c7ad143c113c25f40cf2ef39d55e459 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 29 Aug 2026 19:57:14 -0700 Subject: [PATCH 13/21] terminal: fix living item over-count in RefCountedSet.addWithId Reported in https://github.com/ghostty-org/ghostty/discussions/14064 I validated this myself manually. The zero-ref branch of `addWithIdContext` incremented `living` unconditionally even if `upsert` resolved the value to an item that was already alive under a different ID. This would cause `living` to be invalid for each time this happened and the downstream effect was that `count()` drifted. I couldn't find any crashing or invalid effect except that this caused requested style memory to be over-provisioned. --- src/terminal/ref_counted_set.zig | 93 +++++++++++++++++++++++++------- 1 file changed, 73 insertions(+), 20 deletions(-) diff --git a/src/terminal/ref_counted_set.zig b/src/terminal/ref_counted_set.zig index 97fa87088..a8e64fcc7 100644 --- a/src/terminal/ref_counted_set.zig +++ b/src/terminal/ref_counted_set.zig @@ -317,6 +317,19 @@ pub fn RefCountedSet( if (id < self.next_id) { if (items[id].meta.ref == 0) { + // Requested ID is dead, but if the value exists not under + // another ID then ref count that and increase the ID. + if (self.lookupContext(base, value, ctx)) |existing_id| { + // Notify the context that the value is "deleted" + // because we're reusing the existing value in the + // set. This allows callers to clean up any + // resources associated with the value. + if (comptime @hasDecl(Context, "deleted")) ctx.deleted(value); + + items[existing_id].meta.ref += 1; + return existing_id; + } + // See comment in `addContext` for details. if (self.psl_stats[self.psl_stats.len - 1] > 0) { @branchHint(.cold); @@ -324,8 +337,7 @@ pub fn RefCountedSet( } self.deleteItem(base, id, ctx); - - const added_id = self.upsert(base, value, id, ctx); + const added_id = self.insert(base, value, id, ctx); items[added_id].meta.ref += 1; @@ -589,24 +601,6 @@ pub fn RefCountedSet( return null; } - /// Find the provided value in the hash table, or add a new item - /// for it if not present. If a new item is added, `new_id` will - /// be used as the ID. If an existing item is found, the `new_id` - /// is ignored and the existing item's ID is returned. - fn upsert(self: *Self, base: anytype, value: T, new_id: Id, ctx: Context) Id { - // If the item already exists, return it. - if (self.lookupContext(base, value, ctx)) |id| { - // Notify the context that the value is "deleted" because - // we're reusing the existing value in the set. This allows - // callers to clean up any resources associated with the value. - if (comptime @hasDecl(Context, "deleted")) ctx.deleted(value); - - return id; - } - - return self.insert(base, value, new_id, ctx); - } - /// Insert the given value into the hash table with the given ID. /// /// If runtime safety is enabled, asserts that @@ -764,6 +758,65 @@ pub fn RefCountedSet( }; } +test "addWithId dead id resolving to an existing value" { + const alloc = testing.allocator; + const TestSet = RefCountedSet( + u32, + u16, + u16, + struct { + pub fn hash(_: *const @This(), value: u32) u64 { + return std.hash.int(value); + } + + pub fn eql(_: *const @This(), a: u32, b: u32) bool { + return a == b; + } + }, + ); + + const layout: TestSet.Layout = .init(8); + const buf = try alloc.alignedAlloc( + u8, + TestSet.base_align, + layout.total_size, + ); + defer alloc.free(buf); + + var set: TestSet = .init(.init(buf), layout, .{}); + + // Create a dead item between two live ones so that it can't + // be reaped by the trim loop in `add`, then release it. This + // mirrors a page style set after a styled run is erased. + const live = try set.add(buf, 11); + const released = try set.add(buf, 22); + const last = try set.add(buf, 33); + set.release(buf, released); + try testing.expectEqual(@as(usize, 2), set.count()); + + // Request the dead ID for a value that is already live under + // a different ID: we must resolve to the existing item and + // take a reference, without changing the living count. + const resolved = (try set.addWithId(buf, 11, released)).?; + try testing.expectEqual(live, resolved); + try testing.expectEqual(@as(u16, 2), set.refCount(buf, live)); + try testing.expectEqual(@as(usize, 2), set.count()); + + // The living count must agree with the iterator. + var it = set.iterator(buf); + var iterated: usize = 0; + while (it.next()) |_| iterated += 1; + try testing.expectEqual(set.count(), iterated); + + // The dead slot is still reusable for a value that is not + // in the set: the requested ID must be used (null return). + try testing.expectEqual(@as(?u16, null), try set.addWithId(buf, 44, released)); + try testing.expectEqual(@as(u16, 1), set.refCount(buf, released)); + try testing.expectEqual(@as(usize, 3), set.count()); + + _ = last; +} + test "iterator visits live entries in ID order" { const alloc = testing.allocator; const TestSet = RefCountedSet( From c181983253129f2803891a2d801951244ae5313c Mon Sep 17 00:00:00 2001 From: Lukas <134181853+bo2themax@users.noreply.github.com> Date: Sun, 30 Aug 2026 10:02:16 +0200 Subject: [PATCH 14/21] build: update Sparkle to 2.9.6 and pin SPM --- .github/workflows/release-tag.yml | 4 ++-- .github/workflows/release-tip.yml | 6 +++--- macos/Ghostty.xcodeproj/project.pbxproj | 4 ++-- .../xcshareddata/swiftpm/Package.resolved | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/release-tag.yml b/.github/workflows/release-tag.yml index 60a2e80e9..42f6f3277 100644 --- a/.github/workflows/release-tag.yml +++ b/.github/workflows/release-tag.yml @@ -160,7 +160,7 @@ jobs: - name: Setup Sparkle env: - SPARKLE_VERSION: 2.9.4 + SPARKLE_VERSION: 2.9.6 run: | mkdir -p .action/sparkle cd .action/sparkle @@ -328,7 +328,7 @@ jobs: - name: Setup Sparkle env: - SPARKLE_VERSION: 2.9.4 + SPARKLE_VERSION: 2.9.6 run: | mkdir -p .action/sparkle cd .action/sparkle diff --git a/.github/workflows/release-tip.yml b/.github/workflows/release-tip.yml index d4e6b7162..12297e03d 100644 --- a/.github/workflows/release-tip.yml +++ b/.github/workflows/release-tip.yml @@ -591,7 +591,7 @@ jobs: # Setup Sparkle - name: Setup Sparkle env: - SPARKLE_VERSION: 2.9.4 + SPARKLE_VERSION: 2.9.6 run: | mkdir -p .action/sparkle cd .action/sparkle @@ -847,7 +847,7 @@ jobs: # Setup Sparkle - name: Setup Sparkle env: - SPARKLE_VERSION: 2.9.4 + SPARKLE_VERSION: 2.9.6 run: | mkdir -p .action/sparkle cd .action/sparkle @@ -1044,7 +1044,7 @@ jobs: # Setup Sparkle - name: Setup Sparkle env: - SPARKLE_VERSION: 2.9.4 + SPARKLE_VERSION: 2.9.6 run: | mkdir -p .action/sparkle cd .action/sparkle diff --git a/macos/Ghostty.xcodeproj/project.pbxproj b/macos/Ghostty.xcodeproj/project.pbxproj index 96cbaca0a..544f61ba5 100644 --- a/macos/Ghostty.xcodeproj/project.pbxproj +++ b/macos/Ghostty.xcodeproj/project.pbxproj @@ -1099,8 +1099,8 @@ isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/sparkle-project/Sparkle"; requirement = { - kind = upToNextMajorVersion; - minimumVersion = 2.5.1; + kind = exactVersion; + version = 2.9.6; }; }; /* End XCRemoteSwiftPackageReference section */ diff --git a/macos/Ghostty.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/macos/Ghostty.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index feb7b4ba0..5ed508c36 100644 --- a/macos/Ghostty.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/macos/Ghostty.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -6,8 +6,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/sparkle-project/Sparkle", "state" : { - "revision" : "b6496a74a087257ef5e6da1c5b29a447a60f5bd7", - "version" : "2.9.4" + "revision" : "ac2def288cbff5cfc7df3ffef6abdf45b72bcb0a", + "version" : "2.9.6" } } ], From 6d850fef7780f3461ee526eba16077ea9d7df8a6 Mon Sep 17 00:00:00 2001 From: "ghostty-vouch[bot]" <262049992+ghostty-vouch[bot]@users.noreply.github.com> Date: Sun, 30 Aug 2026 08:12:01 +0000 Subject: [PATCH 15/21] Update VOUCHED list (#14084) Triggered by [discussion comment](https://github.com/ghostty-org/ghostty/discussions/14083#discussioncomment-18204946) from @jcollie. Vouch: @mgsloan Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .github/VOUCHED.td | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/VOUCHED.td b/.github/VOUCHED.td index 387df2f1c..33e39a19e 100644 --- a/.github/VOUCHED.td +++ b/.github/VOUCHED.td @@ -212,6 +212,7 @@ marrocco-simone masterflitzer matkotiric mattn +mgsloan micaeljarniac michielvk miguelelgallo From 3e2c0fa2db39215ee3b8098181baca7feb04ec27 Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Sun, 30 Aug 2026 02:00:27 -0600 Subject: [PATCH 16/21] gtk: do not warn when gtk-xft-dpi is -1 Before this change, ghostty frequently logs the following warning, even though a `gtk-xft-dpi` value of `-1` is valid and indicates default scaling. ``` warning(gtk_ghostty_surface): gtk-xft-dpi has invalid value (-1), using default ``` From [the gtk docs](https://docs.gtk.org/gtk4/property.Settings.gtk-xft-dpi.html): > The font resolution, in 1024 * dots/inch. > > -1 to use the default value. --- src/apprt/gtk/class/surface.zig | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/apprt/gtk/class/surface.zig b/src/apprt/gtk/class/surface.zig index 59d8ed0f7..408935125 100644 --- a/src/apprt/gtk/class/surface.zig +++ b/src/apprt/gtk/class/surface.zig @@ -1572,12 +1572,13 @@ pub const Surface = extern struct { break :xft_scale 1.0; }; - // Use a value of 1.0 for the XFT DPI scale if the setting is <= 0 - // See: - // https://gitlab.gnome.org/GNOME/libadwaita/-/commit/a7738a4d269bfdf4d8d5429ca73ccdd9b2450421 + // -1 specifies default scale. See: + // https://docs.gtk.org/gtk4/property.Settings.gtk-xft-dpi.html // https://gitlab.gnome.org/GNOME/libadwaita/-/commit/9759d3fd81129608dd78116001928f2aed974ead if (gtk_xft_dpi <= 0) { - log.warn("gtk-xft-dpi has invalid value ({}), using default", .{gtk_xft_dpi}); + if (gtk_xft_dpi != -1) { + log.warn("gtk-xft-dpi has invalid value ({}), using default", .{gtk_xft_dpi}); + } break :xft_scale 1.0; } From 860cfb1d7958d0c5af09ff23488cfa6ea6665b46 Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Sun, 30 Aug 2026 02:31:42 -0600 Subject: [PATCH 17/21] Address review feedback --- src/apprt/gtk/class/surface.zig | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/apprt/gtk/class/surface.zig b/src/apprt/gtk/class/surface.zig index 408935125..9d45bc6ce 100644 --- a/src/apprt/gtk/class/surface.zig +++ b/src/apprt/gtk/class/surface.zig @@ -1572,10 +1572,13 @@ pub const Surface = extern struct { break :xft_scale 1.0; }; - // -1 specifies default scale. See: - // https://docs.gtk.org/gtk4/property.Settings.gtk-xft-dpi.html + // Use a value of 1.0 for the XFT DPI scale if the setting is <= 0 + // See: + // https://gitlab.gnome.org/GNOME/libadwaita/-/commit/a7738a4d269bfdf4d8d5429ca73ccdd9b2450421 // https://gitlab.gnome.org/GNOME/libadwaita/-/commit/9759d3fd81129608dd78116001928f2aed974ead if (gtk_xft_dpi <= 0) { + // -1 is a valid value which specifies default scale. + // https://docs.gtk.org/gtk4/property.Settings.gtk-xft-dpi.html if (gtk_xft_dpi != -1) { log.warn("gtk-xft-dpi has invalid value ({}), using default", .{gtk_xft_dpi}); } From ec3e384d2d7d86206fc3c71aa23a76b7bdb5eae9 Mon Sep 17 00:00:00 2001 From: "ghostty-vouch[bot]" <262049992+ghostty-vouch[bot]@users.noreply.github.com> Date: Mon, 31 Aug 2026 00:01:05 +0000 Subject: [PATCH 18/21] Sync CODEOWNERS vouch list (#14090) Sync CODEOWNERS owners with vouch list. ## Added Users - @jakeriksen - @Kleshzz Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .github/VOUCHED.td | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/VOUCHED.td b/.github/VOUCHED.td index 33e39a19e..09b9c2ab4 100644 --- a/.github/VOUCHED.td +++ b/.github/VOUCHED.td @@ -161,6 +161,7 @@ j-c-m j0hnm4r5 jacobsandlund jake-stewart +jakeriksen -jamesarch Bad AI etiquette jamylak jarred-sumner @@ -184,6 +185,7 @@ khipp kierancanter kirwiisp kjvdven +kleshzz kloneets knu -kody-w From e8aa098674a42e2b4ed1b8c42f4224564ad9fc1e Mon Sep 17 00:00:00 2001 From: "ghostty-vouch[bot]" <262049992+ghostty-vouch[bot]@users.noreply.github.com> Date: Mon, 31 Aug 2026 03:00:47 +0000 Subject: [PATCH 19/21] Update VOUCHED list (#14092) Triggered by [discussion comment](https://github.com/ghostty-org/ghostty/discussions/14091#discussioncomment-18212381) from @pluiedev. Denounce: @thomas-trijindev Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .github/VOUCHED.td | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/VOUCHED.td b/.github/VOUCHED.td index 09b9c2ab4..3f46fbd76 100644 --- a/.github/VOUCHED.td +++ b/.github/VOUCHED.td @@ -314,6 +314,7 @@ tbrundige tdgroot tdslot thirstycrow +-thomas-trijindev No human in the loop thoutbeckers ticclick tnagatomi From dfccdb2d4dfdfa9da14664ae06f56f3db923d1e2 Mon Sep 17 00:00:00 2001 From: "Mohammad H. AlShami" Date: Thu, 7 May 2026 01:25:51 +0300 Subject: [PATCH 20/21] Implement needed modifications for issue #12600 For middle-click-action * Kept the option "primary-paste" instead of "paste-primary" to keep backwards compatibility * Added the option "clipboard-paste" For copy-on-select * Added the both, none and primary options Updated config documentation Run zig fmt Move true/false options for copy-on-select to the compatibility handler Update src/config/Config.zig Co-authored-by: kat <65649991+00-kat@users.noreply.github.com> Update src/config/Config.zig Co-authored-by: kat <65649991+00-kat@users.noreply.github.com> Update src/config/Config.zig Co-authored-by: kat <65649991+00-kat@users.noreply.github.com> Update src/config/Config.zig Co-authored-by: kat <65649991+00-kat@users.noreply.github.com> Update src/config/Config.zig Co-authored-by: kat <65649991+00-kat@users.noreply.github.com> Update src/config/Config.zig Co-authored-by: kat <65649991+00-kat@users.noreply.github.com> Update src/Surface.zig Co-authored-by: kat <65649991+00-kat@users.noreply.github.com> Update src/Surface.zig Co-authored-by: kat <65649991+00-kat@users.noreply.github.com> Update src/config/Config.zig Co-authored-by: kat <65649991+00-kat@users.noreply.github.com> Update src/config/Config.zig Co-authored-by: kat <65649991+00-kat@users.noreply.github.com> Update src/config/Config.zig Co-authored-by: kat <65649991+00-kat@users.noreply.github.com> Update src/config/Config.zig Co-authored-by: kat <65649991+00-kat@users.noreply.github.com> Update src/config/Config.zig Co-authored-by: kat <65649991+00-kat@users.noreply.github.com> Update src/Surface.zig Co-authored-by: kat <65649991+00-kat@users.noreply.github.com> Update src/Surface.zig Co-authored-by: kat <65649991+00-kat@users.noreply.github.com> Reorder switch items Apply comment from kat Remove redundent code --- src/Surface.zig | 56 ++++++++++++---------------- src/config/Config.zig | 87 +++++++++++++++++++++++++++++++------------ 2 files changed, 88 insertions(+), 55 deletions(-) diff --git a/src/Surface.zig b/src/Surface.zig index 8eddc14c8..5e3f84884 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -2378,31 +2378,29 @@ fn setSelection(self: *Surface, sel_: ?terminal.Selection) !void { fn setSelectionAndCopy(self: *Surface, sel: terminal.Selection) !void { try self.setSelection(sel); - // If copy on select is false then exit early. - if (self.config.copy_on_select == .false) return; - switch (self.config.copy_on_select) { - .false => unreachable, // handled above with an early exit + .none => {}, + + // The selection clipboard is set if supported, otherwise nothing is copied. + .primary => try self.copySelectionToClipboards( + sel, + &.{.selection}, + .mixed, + ), + + // Only the standard clipboard is set. + .clipboard => try self.copySelectionToClipboards( + sel, + &.{.standard}, + .mixed, + ), // Both standard and selection clipboards are set. - .clipboard => try self.copySelectionToClipboards( + .both => try self.copySelectionToClipboards( sel, &.{ .standard, .selection }, .mixed, ), - - // The selection clipboard is set if supported, otherwise the standard. - .true => { - const clipboard: apprt.Clipboard = if (self.rt_surface.supportsClipboard(.selection)) - .selection - else - .standard; - try self.copySelectionToClipboards( - sel, - &.{clipboard}, - .mixed, - ); - }, } } @@ -3891,7 +3889,7 @@ pub fn mouseButtonCallback( // The selection clipboard is only updated for left-click drag when // the left button is released. This is to avoid the clipboard // being updated on every mouse move which would be noisy. - if (self.config.copy_on_select != .false) { + if (self.config.copy_on_select != .none) { const prev_ = self.io.terminal.screens.active.selection; if (prev_) |prev| { try self.setSelectionAndCopy(terminal.Selection.init( @@ -4049,22 +4047,16 @@ pub fn mouseButtonCallback( } } - // Middle-click paste source follows copy-on-select: when copy-on-select - // targets the selection clipboard, middle-click reads from it; when - // copy-on-select targets the system clipboard, middle-click reads from - // that instead. Falls back to the standard clipboard on platforms that - // do not support the selection clipboard. + // Middle-click action, either ignore, or paste from clipboard or paste from the selection clipboard if supported. if (button == .middle and action == .press) switch (self.config.middle_click_action) { .ignore => {}, + .@"clipboard-paste" => { + _ = try self.startClipboardRequest(.standard, .{ .paste = {} }); + }, .@"primary-paste" => { - const clipboard: apprt.Clipboard = switch (self.config.copy_on_select) { - .clipboard => .standard, - .true, .false => if (self.rt_surface.supportsClipboard(.selection)) - .selection - else - .standard, - }; - _ = try self.startClipboardRequest(clipboard, .{ .paste = clipboard }); + if (self.rt_surface.supportsClipboard(.selection)) { + _ = try self.startClipboardRequest(.selection, .{ .paste = {} }); + } }, }; diff --git a/src/config/Config.zig b/src/config/Config.zig index f40614a39..bf4e75f86 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -100,6 +100,12 @@ pub const compatibility = std.StaticStringMap( // Ghostty 1.4 renamed `scrollback-limit` to `scrollback-limit-bytes` // when `scrollback-limit-lines` was added so the units are explicit. .{ "scrollback-limit", cli.compatibilityRenamed(Config, "scrollback-limit-bytes") }, + + // Ghostty 1.4 updated "copy-on-select", allow copying to the selection + // clipboard (on supported operating systems), the system clipboard, or + // both. The semantics also changed but this is the correct mapping. + // See: https://github.com/ghostty-org/ghostty/pull/12604 + .{ "copy-on-select", compatCopyOnSelect }, }); /// Set Ghostty's graphical user interface language to a language other than the @@ -2517,25 +2523,28 @@ keybind: Keybinds = .{}, /// limit per surface is double. @"image-storage-limit": u32 = 320 * 1000 * 1000, -/// Whether to automatically copy selected text to the clipboard. `true` -/// will prefer to copy to the selection clipboard, otherwise it will copy to -/// the system clipboard. +/// Whether to automatically copy selected text to the clipboard. /// -/// The value `clipboard` will always copy text to the selection clipboard -/// as well as the system clipboard. +/// Valid values: /// -/// Middle-click primary paste (see `middle-click-action`) is enabled by -/// default even if this is `false`. The clipboard it pastes from follows -/// this setting: with `true` (or `false`) it reads from the selection -/// clipboard (falling back to the system clipboard on platforms without a -/// selection clipboard); with `clipboard` it reads from the system -/// clipboard. +/// * `none` - Do not copy selected text automatically. /// -/// The default value is true on Linux and macOS. +/// * `primary` - On Linux, copy to the selection clipboard only. This has no +/// effect on macOS. (Available since: 1.4.0) +/// +/// * `clipboard` - Copy text to the system clipboard only. +/// +/// * `both` - Copy to both clipboards on Linux, and only the system clipboard +/// on macOS. (Available since: 1.4.0) +/// +/// For backward compatibility and convenience, a value of `true` is the same as +/// `primary` on Linux and `clipboard` on macOS, and `false` is an alias for +/// `none`. +/// +/// The default value is `primary` on Linux and `none` otherwise. @"copy-on-select": CopyOnSelect = switch (builtin.os.tag) { - .linux => .true, - .macos => .true, - else => .false, + .linux => .primary, + else => .none, }, /// The action to take when the user right-clicks on the terminal surface. @@ -2554,8 +2563,9 @@ keybind: Keybinds = .{}, /// The action to take when the user middle-clicks on the terminal surface. /// /// Valid values: -/// * `primary-paste` - Paste from the selection (or system) clipboard per -/// `copy-on-select`. +/// * `primary-paste` - Paste from the selection clipboard on Linux. +/// Does nothing on macOS. +/// * `clipboard-paste` - Paste from the system clipboard. /// * `ignore` - Do nothing, ignore the middle click. /// /// The default value is `primary-paste`. @@ -5047,6 +5057,31 @@ fn compatMacOSDockDropBehavior( return false; } +fn compatCopyOnSelect( + self: *Config, + alloc: Allocator, + key: []const u8, + value: ?[]const u8, +) bool { + _ = alloc; + assert(std.mem.eql(u8, key, "copy-on-select")); + + if (std.mem.eql(u8, value orelse "", "true")) { + self.@"copy-on-select" = switch (builtin.os.tag) { + .linux, .freebsd => .primary, + else => .clipboard, + }; + return true; + } + + if (std.mem.eql(u8, value orelse "", "false")) { + self.@"copy-on-select" = .none; + return true; + } + + return false; +} + /// Add a diagnostic message to the config with the given string. /// This is always added with a location of "none". pub fn addDiagnosticFmt( @@ -8728,16 +8763,20 @@ pub const RepeatableLink = struct { /// Options for copy on select behavior. pub const CopyOnSelect = enum { - /// Disables copy on select entirely. - false, + /// Disables copy on select entirely. This is the default on macOS. + none, /// Copy on select is enabled, but goes to the selection clipboard. - /// This is not supported on platforms such as macOS. This is the default. - true, + /// This is not supported on platforms such as macOS. This is the default + /// on Linux. + primary, + + /// Copy on select is enabled and goes to the system clipboard. + clipboard, /// Copy on select is enabled and goes to both the system clipboard /// and the selection clipboard (for Linux). - clipboard, + both, }; /// Options for right-click actions. @@ -8761,8 +8800,10 @@ pub const RightClickAction = enum { /// Options for middle-click actions. pub const MiddleClickAction = enum { - /// Paste from the selection/standard clipboard per `copy-on-select`. + /// Paste from the selection clipboard. @"primary-paste", + /// Paste from the standard clipboard. + @"clipboard-paste", /// No action is taken on middle click. ignore, From e80ce2ed4cc603c0b52f9cb344f39c64048478e0 Mon Sep 17 00:00:00 2001 From: "Mohammad H. AlShami" Date: Mon, 31 Aug 2026 10:28:59 +0300 Subject: [PATCH 21/21] Fix build error --- src/Surface.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Surface.zig b/src/Surface.zig index 5e3f84884..775292127 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -4051,11 +4051,11 @@ pub fn mouseButtonCallback( if (button == .middle and action == .press) switch (self.config.middle_click_action) { .ignore => {}, .@"clipboard-paste" => { - _ = try self.startClipboardRequest(.standard, .{ .paste = {} }); + _ = try self.startClipboardRequest(.standard, .{ .paste = .standard }); }, .@"primary-paste" => { if (self.rt_surface.supportsClipboard(.selection)) { - _ = try self.startClipboardRequest(.selection, .{ .paste = {} }); + _ = try self.startClipboardRequest(.selection, .{ .paste = .selection }); } }, };