mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-09-06 19:38:23 +00:00
Compare commits
22 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
889478f310 | ||
![]() |
8bd3073cb7 | ||
![]() |
acafe881a0 | ||
![]() |
80030f20f0 | ||
![]() |
602b47ff4e | ||
![]() |
3a7fb03ef9 | ||
![]() |
3423cfdc71 | ||
![]() |
b2a8211f9e | ||
![]() |
8fdb3e6e99 | ||
![]() |
f1c510f9fe | ||
![]() |
3264051f8d | ||
![]() |
b2ad90fe18 | ||
![]() |
9d5e64a76f | ||
![]() |
691fbccbfc | ||
![]() |
92bd6b6244 | ||
![]() |
ccf72dfbf7 | ||
![]() |
196bc55757 | ||
![]() |
f458d48f9b | ||
![]() |
adf7c87cb2 | ||
![]() |
c9ca09af90 | ||
![]() |
e30b5efd5d | ||
![]() |
67650c273a |
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -1,4 +1,6 @@
|
||||
build.zig.zon.nix linguist-generated=true
|
||||
build.zig.zon.txt linguist-generated=true
|
||||
build.zig.zon2json-lock linguist-generated=true
|
||||
vendor/** linguist-vendored
|
||||
website/** linguist-documentation
|
||||
pkg/breakpad/vendor/** linguist-vendored
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -18,4 +18,3 @@ glad.zip
|
||||
/Box_test.ppm
|
||||
/Box_test_diff.ppm
|
||||
/ghostty.qcow2
|
||||
/build.zig.zon2json-lock
|
||||
|
@@ -23,13 +23,6 @@ https://release.files.ghostty.org/VERSION/ghostty-VERSION.tar.gz
|
||||
https://release.files.ghostty.org/VERSION/ghostty-VERSION.tar.gz.minisig
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> **Version 1.0.0 the filename is `ghostty-source.tar.gz`.** Future
|
||||
> versions will use the `ghostty-VERSION.tar.gz` format since it is more
|
||||
> typical for source tarballs. But for version 1.0.0, the filename is
|
||||
> `ghostty-source.tar.gz`.
|
||||
|
||||
Signature files are signed with
|
||||
[minisign](https://jedisct1.github.io/minisign/)
|
||||
using the following public key:
|
||||
|
@@ -1,6 +1,6 @@
|
||||
.{
|
||||
.name = "ghostty",
|
||||
.version = "1.1.2",
|
||||
.version = "1.1.3",
|
||||
.paths = .{""},
|
||||
.dependencies = .{
|
||||
// Zig libs
|
||||
@@ -14,11 +14,11 @@
|
||||
.lazy = true,
|
||||
},
|
||||
.vaxis = .{
|
||||
.url = "git+https://github.com/rockorager/libvaxis/?ref=main#6d729a2dc3b934818dffe06d2ba3ce02841ed74b",
|
||||
.url = "https://github.com/rockorager/libvaxis/archive/6d729a2dc3b934818dffe06d2ba3ce02841ed74b.tar.gz",
|
||||
.hash = "12200df4ebeaed45de26cb2c9f3b6f3746d8013b604e035dae658f86f586c8c91d2f",
|
||||
},
|
||||
.z2d = .{
|
||||
.url = "git+https://github.com/vancluever/z2d?ref=v0.4.0#4638bb02a9dc41cc2fb811f092811f6a951c752a",
|
||||
.url = "https://github.com/vancluever/z2d/archive/4638bb02a9dc41cc2fb811f092811f6a951c752a.tar.gz",
|
||||
.hash = "12201f0d542e7541cf492a001d4d0d0155c92f58212fbcb0d224e95edeba06b5416a",
|
||||
},
|
||||
.zig_objc = .{
|
||||
@@ -38,7 +38,7 @@
|
||||
.hash = "12209ca054cb1919fa276e328967f10b253f7537c4136eb48f3332b0f7cf661cad38",
|
||||
},
|
||||
.zf = .{
|
||||
.url = "git+https://github.com/natecraddock/zf/?ref=main#ed99ca18b02dda052e20ba467e90b623c04690dd",
|
||||
.url = "https://github.com/natecraddock/zf/archive/ed99ca18b02dda052e20ba467e90b623c04690dd.tar.gz",
|
||||
.hash = "1220edc3b8d8bedbb50555947987e5e8e2f93871ca3c8e8d4cc8f1377c15b5dd35e8",
|
||||
},
|
||||
.gobject = .{
|
||||
@@ -76,7 +76,7 @@
|
||||
.hash = "12201a57c6ce0001aa034fa80fba3e1cd2253c560a45748f4f4dd21ff23b491cddef",
|
||||
},
|
||||
.plasma_wayland_protocols = .{
|
||||
.url = "git+https://github.com/KDE/plasma-wayland-protocols?ref=main#db525e8f9da548cffa2ac77618dd0fbe7f511b86",
|
||||
.url = "https://github.com/KDE/plasma-wayland-protocols/archive/db525e8f9da548cffa2ac77618dd0fbe7f511b86.tar.gz",
|
||||
.hash = "12207e0851c12acdeee0991e893e0132fc87bb763969a585dc16ecca33e88334c566",
|
||||
},
|
||||
|
||||
|
22
build.zig.zon.nix
generated
22
build.zig.zon.nix
generated
@@ -143,8 +143,8 @@ in
|
||||
name = "12200df4ebeaed45de26cb2c9f3b6f3746d8013b604e035dae658f86f586c8c91d2f";
|
||||
path = fetchZigArtifact {
|
||||
name = "vaxis";
|
||||
url = "git+https://github.com/rockorager/libvaxis/?ref=main#6d729a2dc3b934818dffe06d2ba3ce02841ed74b";
|
||||
hash = "sha256-fFf79fCy4QQFVNcN722tSMjB6FyVEzCB36oH1olk9JQ=";
|
||||
url = "https://github.com/rockorager/libvaxis/archive/6d729a2dc3b934818dffe06d2ba3ce02841ed74b.tar.gz";
|
||||
hash = "sha256-OCNs6Gl2ruq5dBm4uIxs93hoXw/+n+x1+bIDfQGDx3s=";
|
||||
};
|
||||
}
|
||||
{
|
||||
@@ -167,8 +167,8 @@ in
|
||||
name = "12201f0d542e7541cf492a001d4d0d0155c92f58212fbcb0d224e95edeba06b5416a";
|
||||
path = fetchZigArtifact {
|
||||
name = "z2d";
|
||||
url = "git+https://github.com/vancluever/z2d?ref=v0.4.0#4638bb02a9dc41cc2fb811f092811f6a951c752a";
|
||||
hash = "sha256-YpWXn1J3JKQSCrWB25mAfzd1/T56QstEZnhPzBwxgoM=";
|
||||
url = "https://github.com/vancluever/z2d/archive/4638bb02a9dc41cc2fb811f092811f6a951c752a.tar.gz";
|
||||
hash = "sha256-P0UJ54RO/vVyDa+UkBl+QEOjzoMMEFSOTexQP/uBXfc=";
|
||||
};
|
||||
}
|
||||
{
|
||||
@@ -207,8 +207,8 @@ in
|
||||
name = "1220edc3b8d8bedbb50555947987e5e8e2f93871ca3c8e8d4cc8f1377c15b5dd35e8";
|
||||
path = fetchZigArtifact {
|
||||
name = "zf";
|
||||
url = "git+https://github.com/natecraddock/zf/?ref=main#ed99ca18b02dda052e20ba467e90b623c04690dd";
|
||||
hash = "sha256-t6QNrEJZ4GZZsYixjYvpdrYoCmNbG8TTUmGs2MFa4sU=";
|
||||
url = "https://github.com/natecraddock/zf/archive/ed99ca18b02dda052e20ba467e90b623c04690dd.tar.gz";
|
||||
hash = "sha256-/oLryY3VQfjbtQi+UP+n6FJTVA/YxIetjO+6Ovrh6/E=";
|
||||
};
|
||||
}
|
||||
{
|
||||
@@ -232,7 +232,7 @@ in
|
||||
path = fetchZigArtifact {
|
||||
name = "wayland";
|
||||
url = "https://deps.files.ghostty.org/wayland-9cb3d7aa9dc995ffafdbdef7ab86a949d0fb0e7d.tar.gz";
|
||||
hash = "sha256-m9G72jdG30KH2yQhNBcBJ46OnekzuX0i2uIOyczkpLk=";
|
||||
hash = "sha256-6kGR1o5DdnflHzqs3ieCmBAUTpMdOXoyfcYDXiw5xQ0=";
|
||||
};
|
||||
}
|
||||
{
|
||||
@@ -247,8 +247,8 @@ in
|
||||
name = "12207e0851c12acdeee0991e893e0132fc87bb763969a585dc16ecca33e88334c566";
|
||||
path = fetchZigArtifact {
|
||||
name = "plasma_wayland_protocols";
|
||||
url = "git+https://github.com/KDE/plasma-wayland-protocols?ref=main#db525e8f9da548cffa2ac77618dd0fbe7f511b86";
|
||||
hash = "sha256-iWRv3+OfmHxmeCJ8m0ChjgZX6mwXlcFmK8P/Vt8gDj4=";
|
||||
url = "https://github.com/KDE/plasma-wayland-protocols/archive/db525e8f9da548cffa2ac77618dd0fbe7f511b86.tar.gz";
|
||||
hash = "sha256-XFi6IUrNjmvKNCbcCLAixGqN2Zeymhs+KLrfccIN9EE=";
|
||||
};
|
||||
}
|
||||
{
|
||||
@@ -367,8 +367,8 @@ in
|
||||
name = "12207ff340169c7d40c570b4b6a97db614fe47e0d83b5801a932dcd44917424c8806";
|
||||
path = fetchZigArtifact {
|
||||
name = "pixels";
|
||||
url = "git+https://github.com/make-github-pseudonymous-again/pixels?ref=main#d843c2714d32e15b48b8d7eeb480295af537f877";
|
||||
hash = "sha256-kXYGO0qn2PfyOYCrRA49BHIgTzdmKhI8SNO1ZKfUYEE=";
|
||||
url = "https://github.com/make-github-pseudonymous-again/pixels/archive/d843c2714d32e15b48b8d7eeb480295af537f877.tar.gz";
|
||||
hash = "sha256-Veg7FtCRCCUCvxSb9FfzH0IJLFmCZQ4/+657SIcb8Ro=";
|
||||
};
|
||||
}
|
||||
{
|
||||
|
38
build.zig.zon.txt
generated
Normal file
38
build.zig.zon.txt
generated
Normal file
@@ -0,0 +1,38 @@
|
||||
git+https://github.com/rockorager/libvaxis/?ref=main#dc0a228a5544988d4a920cfb40be9cd28db41423
|
||||
git+https://github.com/zigimg/zigimg#3a667bdb3d7f0955a5a51c8468eac83210c1439e
|
||||
https://codeberg.org/atman/zg/archive/v0.13.2.tar.gz
|
||||
https://deps.files.ghostty.org/fontconfig-2.14.2.tar.gz
|
||||
https://deps.files.ghostty.org/wayland-9cb3d7aa9dc995ffafdbdef7ab86a949d0fb0e7d.tar.gz
|
||||
https://deps.files.ghostty.org/wayland-protocols-258d8f88f2c8c25a830c6316f87d23ce1a0f12d9.tar.gz
|
||||
https://deps.files.ghostty.org/zig-wayland-fbfe3b4ac0b472a27b1f1a67405436c58cbee12d.tar.gz
|
||||
https://deps.files.ghostty.org/ziglyph-b89d43d1e3fb01b6074bc1f7fc980324b04d26a5.tar.gz
|
||||
https://github.com/GNOME/libxml2/archive/refs/tags/v2.11.5.tar.gz
|
||||
https://github.com/KDE/plasma-wayland-protocols/archive/db525e8f9da548cffa2ac77618dd0fbe7f511b86.tar.gz
|
||||
https://github.com/KhronosGroup/SPIRV-Cross/archive/476f384eb7d9e48613c45179e502a15ab95b6b49.tar.gz
|
||||
https://github.com/KhronosGroup/glslang/archive/refs/tags/14.2.0.tar.gz
|
||||
https://github.com/freetype/freetype/archive/refs/tags/VER-2-13-2.tar.gz
|
||||
https://github.com/getsentry/breakpad/archive/b99f444ba5f6b98cac261cbb391d8766b34a5918.tar.gz
|
||||
https://github.com/getsentry/sentry-native/archive/refs/tags/0.7.8.tar.gz
|
||||
https://github.com/glennrp/libpng/archive/refs/tags/v1.6.43.tar.gz
|
||||
https://github.com/google/highway/archive/refs/tags/1.1.0.tar.gz
|
||||
https://github.com/google/wuffs/archive/refs/tags/v0.4.0-alpha.9.tar.gz
|
||||
https://github.com/harfbuzz/harfbuzz/archive/refs/tags/8.4.0.tar.gz
|
||||
https://github.com/ianprime0509/zig-gobject/releases/download/v0.2.2/bindings-gnome47.tar.zst
|
||||
https://github.com/kkos/oniguruma/archive/refs/tags/v6.9.9.tar.gz
|
||||
https://github.com/madler/zlib/archive/refs/tags/v1.3.1.tar.gz
|
||||
https://github.com/make-github-pseudonymous-again/pixels/archive/d843c2714d32e15b48b8d7eeb480295af537f877.tar.gz
|
||||
https://github.com/mbadolato/iTerm2-Color-Schemes/archive/db227d159adc265818f2e898da0f70ef8d7b580e.tar.gz
|
||||
https://github.com/mitchellh/glfw/archive/b552c6ec47326b94015feddb36058ea567b87159.tar.gz
|
||||
https://github.com/mitchellh/libxev/archive/31eed4e337fed7b0149319e5cdbb62b848c24fbd.tar.gz
|
||||
https://github.com/mitchellh/mach-glfw/archive/37c2995f31abcf7e8378fba68ddcf4a3faa02de0.tar.gz
|
||||
https://github.com/mitchellh/vulkan-headers/archive/04c8a0389d5a0236a96312988017cd4ce27d8041.tar.gz
|
||||
https://github.com/mitchellh/wayland-headers/archive/5f991515a29f994d87b908115a2ab0b899474bd1.tar.gz
|
||||
https://github.com/mitchellh/x11-headers/archive/2ffbd62d82ff73ec929dd8de802bc95effa0ef88.tar.gz
|
||||
https://github.com/mitchellh/xcode-frameworks/archive/69801c154c39d7ae6129ea1ba8fe1afe00585fc8.tar.gz
|
||||
https://github.com/mitchellh/zig-js/archive/d0b8b0a57c52fbc89f9d9fecba75ca29da7dd7d1.tar.gz
|
||||
https://github.com/mitchellh/zig-objc/archive/9b8ba849b0f58fe207ecd6ab7c147af55b17556e.tar.gz
|
||||
https://github.com/natecraddock/zf/archive/ed99ca18b02dda052e20ba467e90b623c04690dd.tar.gz
|
||||
https://github.com/nemtrif/utfcpp/archive/refs/tags/v4.0.5.tar.gz
|
||||
https://github.com/ocornut/imgui/archive/e391fe2e66eb1c96b1624ae8444dc64c23146ef4.tar.gz
|
||||
https://github.com/rockorager/libvaxis/archive/6d729a2dc3b934818dffe06d2ba3ce02841ed74b.tar.gz
|
||||
https://github.com/vancluever/z2d/archive/4638bb02a9dc41cc2fb811f092811f6a951c752a.tar.gz
|
192
build.zig.zon2json-lock
generated
Normal file
192
build.zig.zon2json-lock
generated
Normal file
@@ -0,0 +1,192 @@
|
||||
{
|
||||
"1220ebf88622c4d502dc59e71347e4d28c47e033f11b59aff774ae5787565c40999c": {
|
||||
"name": "libxev",
|
||||
"url": "https://github.com/mitchellh/libxev/archive/31eed4e337fed7b0149319e5cdbb62b848c24fbd.tar.gz",
|
||||
"hash": "sha256-VHP90NTytIZ8UZsYRKOOxN490/I6yv6ec40sP8y5MJ8="
|
||||
},
|
||||
"12206ed982e709e565d536ce930701a8c07edfd2cfdce428683f3f2a601d37696a62": {
|
||||
"name": "mach_glfw",
|
||||
"url": "https://github.com/mitchellh/mach-glfw/archive/37c2995f31abcf7e8378fba68ddcf4a3faa02de0.tar.gz",
|
||||
"hash": "sha256-HhXIvWUS8/CHWY4VXPG2ZEo+we8XOn3o5rYJCQ1n8Nk="
|
||||
},
|
||||
"1220736fa4ba211162c7a0e46cc8fe04d95921927688bff64ab5da7420d098a7272d": {
|
||||
"name": "glfw",
|
||||
"url": "https://github.com/mitchellh/glfw/archive/b552c6ec47326b94015feddb36058ea567b87159.tar.gz",
|
||||
"hash": "sha256-IeBVAOQmtyFqVxzuXPek1onuPwIamcOyYtxqKpPEQjU="
|
||||
},
|
||||
"12202adbfecdad671d585c9a5bfcbd5cdf821726779430047742ce1bf94ad67d19cb": {
|
||||
"name": "xcode_frameworks",
|
||||
"url": "https://github.com/mitchellh/xcode-frameworks/archive/69801c154c39d7ae6129ea1ba8fe1afe00585fc8.tar.gz",
|
||||
"hash": "sha256-mP/I2coL57UJm/3+4Q8sPAgQwk8V4zM+S4VBBTrX2To="
|
||||
},
|
||||
"122004bfd4c519dadfb8e6281a42fc34fd1aa15aea654ea8a492839046f9894fa2cf": {
|
||||
"name": "vulkan_headers",
|
||||
"url": "https://github.com/mitchellh/vulkan-headers/archive/04c8a0389d5a0236a96312988017cd4ce27d8041.tar.gz",
|
||||
"hash": "sha256-K+zrRudgHFukOM6En1StRYRMNYkeRk+qHTXvrXaG+FU="
|
||||
},
|
||||
"1220b3164434d2ec9db146a40bf3a30f490590d68fa8529776a3138074f0da2c11ca": {
|
||||
"name": "wayland_headers",
|
||||
"url": "https://github.com/mitchellh/wayland-headers/archive/5f991515a29f994d87b908115a2ab0b899474bd1.tar.gz",
|
||||
"hash": "sha256-uFilLZinKkZt6RdVTV3lUmJpzpswDdFva22FvwU/XQI="
|
||||
},
|
||||
"122089c326186c84aa2fd034b16abc38f3ebf4862d9ae106dc1847ac44f557b36465": {
|
||||
"name": "x11_headers",
|
||||
"url": "https://github.com/mitchellh/x11-headers/archive/2ffbd62d82ff73ec929dd8de802bc95effa0ef88.tar.gz",
|
||||
"hash": "sha256-EhV2bmTY/OMYN1wEul35gD0hQgS/Al262jO3pVr0O+c="
|
||||
},
|
||||
"12200df4ebeaed45de26cb2c9f3b6f3746d8013b604e035dae658f86f586c8c91d2f": {
|
||||
"name": "vaxis",
|
||||
"url": "https://github.com/rockorager/libvaxis/archive/6d729a2dc3b934818dffe06d2ba3ce02841ed74b.tar.gz",
|
||||
"hash": "sha256-OCNs6Gl2ruq5dBm4uIxs93hoXw/+n+x1+bIDfQGDx3s="
|
||||
},
|
||||
"1220dd654ef941fc76fd96f9ec6adadf83f69b9887a0d3f4ee5ac0a1a3e11be35cf5": {
|
||||
"name": "zigimg",
|
||||
"url": "git+https://github.com/zigimg/zigimg#3a667bdb3d7f0955a5a51c8468eac83210c1439e",
|
||||
"hash": "sha256-oLf3YH3yeg4ikVO/GahMCDRMTU31AHkfSnF4rt7xTKo="
|
||||
},
|
||||
"122055beff332830a391e9895c044d33b15ea21063779557024b46169fb1984c6e40": {
|
||||
"name": "zg",
|
||||
"url": "https://codeberg.org/atman/zg/archive/v0.13.2.tar.gz",
|
||||
"hash": "sha256-2x9hT7bYq9KJYWLVOf21a+QvTG/F7HWT+YK15IMRzNY="
|
||||
},
|
||||
"12201f0d542e7541cf492a001d4d0d0155c92f58212fbcb0d224e95edeba06b5416a": {
|
||||
"name": "z2d",
|
||||
"url": "https://github.com/vancluever/z2d/archive/4638bb02a9dc41cc2fb811f092811f6a951c752a.tar.gz",
|
||||
"hash": "sha256-P0UJ54RO/vVyDa+UkBl+QEOjzoMMEFSOTexQP/uBXfc="
|
||||
},
|
||||
"1220e17e64ef0ef561b3e4b9f3a96a2494285f2ec31c097721bf8c8677ec4415c634": {
|
||||
"name": "zig_objc",
|
||||
"url": "https://github.com/mitchellh/zig-objc/archive/9b8ba849b0f58fe207ecd6ab7c147af55b17556e.tar.gz",
|
||||
"hash": "sha256-H+HIbh2T23uzrsg9/1/vl9Ir1HCAa2pzeTx6zktJH9Q="
|
||||
},
|
||||
"12205a66d423259567764fa0fc60c82be35365c21aeb76c5a7dc99698401f4f6fefc": {
|
||||
"name": "zig_js",
|
||||
"url": "https://github.com/mitchellh/zig-js/archive/d0b8b0a57c52fbc89f9d9fecba75ca29da7dd7d1.tar.gz",
|
||||
"hash": "sha256-fyNeCVbC9UAaKJY6JhAZlT0A479M/AKYMPIWEZbDWD0="
|
||||
},
|
||||
"12207831bce7d4abce57b5a98e8f3635811cfefd160bca022eb91fe905d36a02cf25": {
|
||||
"name": "ziglyph",
|
||||
"url": "https://deps.files.ghostty.org/ziglyph-b89d43d1e3fb01b6074bc1f7fc980324b04d26a5.tar.gz",
|
||||
"hash": "sha256-cse98+Ft8QUjX+P88yyYfaxJOJGQ9M7Ymw7jFxDz89k="
|
||||
},
|
||||
"12209ca054cb1919fa276e328967f10b253f7537c4136eb48f3332b0f7cf661cad38": {
|
||||
"name": "zig_wayland",
|
||||
"url": "https://deps.files.ghostty.org/zig-wayland-fbfe3b4ac0b472a27b1f1a67405436c58cbee12d.tar.gz",
|
||||
"hash": "sha256-RtAystqK/GRYIquTK1KfD7rRSCrfuzAvCD1Z9DE1ldc="
|
||||
},
|
||||
"1220edc3b8d8bedbb50555947987e5e8e2f93871ca3c8e8d4cc8f1377c15b5dd35e8": {
|
||||
"name": "zf",
|
||||
"url": "https://github.com/natecraddock/zf/archive/ed99ca18b02dda052e20ba467e90b623c04690dd.tar.gz",
|
||||
"hash": "sha256-/oLryY3VQfjbtQi+UP+n6FJTVA/YxIetjO+6Ovrh6/E="
|
||||
},
|
||||
"1220c72c1697dd9008461ead702997a15d8a1c5810247f02e7983b9f74c6c6e4c087": {
|
||||
"name": "vaxis",
|
||||
"url": "git+https://github.com/rockorager/libvaxis/?ref=main#dc0a228a5544988d4a920cfb40be9cd28db41423",
|
||||
"hash": "sha256-QWN4jOrA91KlbqmeEHHJ4HTnCC9nmfxt8DHUXJpAzLI="
|
||||
},
|
||||
"12208d70ee791d7ef7e16e1c3c9c1127b57f1ed066a24f87d57fc9f730c5dc394b9d": {
|
||||
"name": "gobject",
|
||||
"url": "https://github.com/ianprime0509/zig-gobject/releases/download/v0.2.2/bindings-gnome47.tar.zst",
|
||||
"hash": "sha256-UU97kNv/bZzQPKz1djhEDLapLguvfBpFfWVb6FthtcI="
|
||||
},
|
||||
"12202cdac858abc52413a6c6711d5026d2d3c8e13f95ca2c327eade0736298bb021f": {
|
||||
"name": "wayland",
|
||||
"url": "https://deps.files.ghostty.org/wayland-9cb3d7aa9dc995ffafdbdef7ab86a949d0fb0e7d.tar.gz",
|
||||
"hash": "sha256-6kGR1o5DdnflHzqs3ieCmBAUTpMdOXoyfcYDXiw5xQ0="
|
||||
},
|
||||
"12201a57c6ce0001aa034fa80fba3e1cd2253c560a45748f4f4dd21ff23b491cddef": {
|
||||
"name": "wayland_protocols",
|
||||
"url": "https://deps.files.ghostty.org/wayland-protocols-258d8f88f2c8c25a830c6316f87d23ce1a0f12d9.tar.gz",
|
||||
"hash": "sha256-XO3K3egbdeYPI+XoO13SuOtO+5+Peb16NH0UiusFMPg="
|
||||
},
|
||||
"12207e0851c12acdeee0991e893e0132fc87bb763969a585dc16ecca33e88334c566": {
|
||||
"name": "plasma_wayland_protocols",
|
||||
"url": "https://github.com/KDE/plasma-wayland-protocols/archive/db525e8f9da548cffa2ac77618dd0fbe7f511b86.tar.gz",
|
||||
"hash": "sha256-XFi6IUrNjmvKNCbcCLAixGqN2Zeymhs+KLrfccIN9EE="
|
||||
},
|
||||
"12203d2647e5daf36a9c85b969e03f422540786ce9ea624eb4c26d204fe1f46218f3": {
|
||||
"name": "iterm2_themes",
|
||||
"url": "https://github.com/mbadolato/iTerm2-Color-Schemes/archive/db227d159adc265818f2e898da0f70ef8d7b580e.tar.gz",
|
||||
"hash": "sha256-Iyf7U4rpvNkPX4AOEbYSYGte5+SjRwsWD2luOn1Hz8U="
|
||||
},
|
||||
"1220bc6b9daceaf7c8c60f3c3998058045ba0c5c5f48ae255ff97776d9cd8bfc6402": {
|
||||
"name": "imgui",
|
||||
"url": "https://github.com/ocornut/imgui/archive/e391fe2e66eb1c96b1624ae8444dc64c23146ef4.tar.gz",
|
||||
"hash": "sha256-oF/QHgTPEat4Hig4fGIdLkIPHmBEyOJ6JeYD6pnveGA="
|
||||
},
|
||||
"1220b81f6ecfb3fd222f76cf9106fecfa6554ab07ec7fdc4124b9bb063ae2adf969d": {
|
||||
"name": "freetype",
|
||||
"url": "https://github.com/freetype/freetype/archive/refs/tags/VER-2-13-2.tar.gz",
|
||||
"hash": "sha256-QnIB9dUVFnDQXB9bRb713aHy592XHvVPD+qqf/0quQw="
|
||||
},
|
||||
"1220aa013f0c83da3fb64ea6d327f9173fa008d10e28bc9349eac3463457723b1c66": {
|
||||
"name": "libpng",
|
||||
"url": "https://github.com/glennrp/libpng/archive/refs/tags/v1.6.43.tar.gz",
|
||||
"hash": "sha256-/syVtGzwXo4/yKQUdQ4LparQDYnp/fF16U/wQcrxoDo="
|
||||
},
|
||||
"1220fed0c74e1019b3ee29edae2051788b080cd96e90d56836eea857b0b966742efb": {
|
||||
"name": "zlib",
|
||||
"url": "https://github.com/madler/zlib/archive/refs/tags/v1.3.1.tar.gz",
|
||||
"hash": "sha256-F+iIY/NgBnKrSRgvIXKBtvxNPHYr3jYZNeQ2qVIU0Fw="
|
||||
},
|
||||
"12201149afb3326c56c05bb0a577f54f76ac20deece63aa2f5cd6ff31a4fa4fcb3b7": {
|
||||
"name": "fontconfig",
|
||||
"url": "https://deps.files.ghostty.org/fontconfig-2.14.2.tar.gz",
|
||||
"hash": "sha256-O6LdkhWHGKzsXKrxpxYEO1qgVcJ7CB2RSvPMtA3OilU="
|
||||
},
|
||||
"122032442d95c3b428ae8e526017fad881e7dc78eab4d558e9a58a80bfbd65a64f7d": {
|
||||
"name": "libxml2",
|
||||
"url": "https://github.com/GNOME/libxml2/archive/refs/tags/v2.11.5.tar.gz",
|
||||
"hash": "sha256-bCgFni4+60K1tLFkieORamNGwQladP7jvGXNxdiaYhU="
|
||||
},
|
||||
"1220b8588f106c996af10249bfa092c6fb2f35fbacb1505ef477a0b04a7dd1063122": {
|
||||
"name": "harfbuzz",
|
||||
"url": "https://github.com/harfbuzz/harfbuzz/archive/refs/tags/8.4.0.tar.gz",
|
||||
"hash": "sha256-nxygiYE7BZRK0c6MfgGCEwJtNdybq0gKIeuHaDg5ZVY="
|
||||
},
|
||||
"12205c83b8311a24b1d5ae6d21640df04f4b0726e314337c043cde1432758cbe165b": {
|
||||
"name": "highway",
|
||||
"url": "https://github.com/google/highway/archive/refs/tags/1.1.0.tar.gz",
|
||||
"hash": "sha256-NUqLRTm1iOcLmOxwhEJz4/J0EwLEw3e8xOgbPRhm98k="
|
||||
},
|
||||
"1220c15e72eadd0d9085a8af134904d9a0f5dfcbed5f606ad60edc60ebeccd9706bb": {
|
||||
"name": "oniguruma",
|
||||
"url": "https://github.com/kkos/oniguruma/archive/refs/tags/v6.9.9.tar.gz",
|
||||
"hash": "sha256-ABqhIC54RI9MC/GkjHblVodrNvFtks4yB+zP1h2Z8qA="
|
||||
},
|
||||
"1220446be831adcca918167647c06c7b825849fa3fba5f22da394667974537a9c77e": {
|
||||
"name": "sentry",
|
||||
"url": "https://github.com/getsentry/sentry-native/archive/refs/tags/0.7.8.tar.gz",
|
||||
"hash": "sha256-KsZJfMjWGo0xCT5HrduMmyxFsWsHBbszSoNbZCPDGN8="
|
||||
},
|
||||
"12207fd37bb8251919c112dcdd8f616a491857b34a451f7e4486490077206dc2a1ea": {
|
||||
"name": "breakpad",
|
||||
"url": "https://github.com/getsentry/breakpad/archive/b99f444ba5f6b98cac261cbb391d8766b34a5918.tar.gz",
|
||||
"hash": "sha256-bMqYlD0amQdmzvYQd8Ca/1k4Bj/heh7+EijlQSttatk="
|
||||
},
|
||||
"1220d4d18426ca72fc2b7e56ce47273149815501d0d2395c2a98c726b31ba931e641": {
|
||||
"name": "utfcpp",
|
||||
"url": "https://github.com/nemtrif/utfcpp/archive/refs/tags/v4.0.5.tar.gz",
|
||||
"hash": "sha256-/8ZooxDndgfTk/PBizJxXyI9oerExNbgV5oR345rWc8="
|
||||
},
|
||||
"122037b39d577ec2db3fd7b2130e7b69ef6cc1807d68607a7c232c958315d381b5cd": {
|
||||
"name": "wuffs",
|
||||
"url": "https://github.com/google/wuffs/archive/refs/tags/v0.4.0-alpha.9.tar.gz",
|
||||
"hash": "sha256-nkzSCr6W5sTG7enDBXEIhgEm574uLD41UVR2wlC+HBM="
|
||||
},
|
||||
"12207ff340169c7d40c570b4b6a97db614fe47e0d83b5801a932dcd44917424c8806": {
|
||||
"name": "pixels",
|
||||
"url": "https://github.com/make-github-pseudonymous-again/pixels/archive/d843c2714d32e15b48b8d7eeb480295af537f877.tar.gz",
|
||||
"hash": "sha256-Veg7FtCRCCUCvxSb9FfzH0IJLFmCZQ4/+657SIcb8Ro="
|
||||
},
|
||||
"12201278a1a05c0ce0b6eb6026c65cd3e9247aa041b1c260324bf29cee559dd23ba1": {
|
||||
"name": "glslang",
|
||||
"url": "https://github.com/KhronosGroup/glslang/archive/refs/tags/14.2.0.tar.gz",
|
||||
"hash": "sha256-FKLtu1Ccs+UamlPj9eQ12/WXFgS0uDPmPmB26MCpl7U="
|
||||
},
|
||||
"1220fb3b5586e8be67bc3feb34cbe749cf42a60d628d2953632c2f8141302748c8da": {
|
||||
"name": "spirv_cross",
|
||||
"url": "https://github.com/KhronosGroup/SPIRV-Cross/archive/476f384eb7d9e48613c45179e502a15ab95b6b49.tar.gz",
|
||||
"hash": "sha256-tStvz8Ref6abHwahNiwVVHNETizAmZVVaxVsU7pmV+M="
|
||||
}
|
||||
}
|
@@ -459,6 +459,11 @@ class QuickTerminalController: BaseTerminalController {
|
||||
ghostty.toggleFullscreen(surface: surface)
|
||||
}
|
||||
|
||||
@IBAction func toggleTerminalInspector(_ sender: Any?) {
|
||||
guard let surface = focusedSurface?.surface else { return }
|
||||
ghostty.toggleTerminalInspector(surface: surface)
|
||||
}
|
||||
|
||||
// MARK: Notifications
|
||||
|
||||
@objc private func applicationWillTerminate(_ notification: Notification) {
|
||||
|
@@ -76,6 +76,12 @@ class TerminalController: BaseTerminalController {
|
||||
selector: #selector(onFrameDidChange),
|
||||
name: NSView.frameDidChangeNotification,
|
||||
object: nil)
|
||||
center.addObserver(
|
||||
self,
|
||||
selector: #selector(onEqualizeSplits),
|
||||
name: Ghostty.Notification.didEqualizeSplits,
|
||||
object: nil
|
||||
)
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
@@ -212,6 +218,9 @@ class TerminalController: BaseTerminalController {
|
||||
// Set our explicit appearance if we need to based on the configuration.
|
||||
window.appearance = surfaceConfig.windowAppearance
|
||||
|
||||
// Update our window light/darkness based on our updated background color
|
||||
window.isLightTheme = OSColor(surfaceConfig.backgroundColor).isLightColor
|
||||
|
||||
// If our window is not visible, then we do nothing. Some things such as blurring
|
||||
// have no effect if the window is not visible. Ultimately, we'll have this called
|
||||
// at some point when a surface becomes focused.
|
||||
@@ -801,6 +810,17 @@ class TerminalController: BaseTerminalController {
|
||||
toggleFullscreen(mode: fullscreenMode)
|
||||
}
|
||||
|
||||
@objc private func onEqualizeSplits(_ notification: Notification) {
|
||||
guard let target = notification.object as? Ghostty.SurfaceView else { return }
|
||||
|
||||
// Check if target surface is in current controller's tree
|
||||
guard surfaceTree?.contains(view: target) ?? false else { return }
|
||||
|
||||
if case .split(let container) = surfaceTree {
|
||||
_ = container.equalize()
|
||||
}
|
||||
}
|
||||
|
||||
struct DerivedConfig {
|
||||
let backgroundColor: Color
|
||||
let macosTitlebarStyle: String
|
||||
|
@@ -95,11 +95,8 @@ class TerminalManager {
|
||||
}
|
||||
}
|
||||
|
||||
// If our app isn't active, we make it active. All new_window actions
|
||||
// force our app to be active.
|
||||
if !NSApp.isActive {
|
||||
// All new_window actions force our app to be active.
|
||||
NSApp.activate(ignoringOtherApps: true)
|
||||
}
|
||||
|
||||
// We're dispatching this async because otherwise the lastCascadePoint doesn't
|
||||
// take effect. Our best theory is there is some next-event-loop-tick logic
|
||||
|
@@ -3,6 +3,10 @@ import Cocoa
|
||||
class TerminalWindow: NSWindow {
|
||||
@objc dynamic var keyEquivalent: String = ""
|
||||
|
||||
/// This is used to determine if certain elements should be drawn light or dark and should
|
||||
/// be updated whenever the window background color or surrounding elements changes.
|
||||
var isLightTheme: Bool = false
|
||||
|
||||
lazy var titlebarColor: NSColor = backgroundColor {
|
||||
didSet {
|
||||
guard let titlebarContainer else { return }
|
||||
@@ -295,7 +299,6 @@ class TerminalWindow: NSWindow {
|
||||
|
||||
|
||||
if newTabButtonImageLayer == nil {
|
||||
let isLightTheme = backgroundColor.isLightColor
|
||||
let fillColor: NSColor = isLightTheme ? .black.withAlphaComponent(0.85) : .white.withAlphaComponent(0.85)
|
||||
let newImage = NSImage(size: newTabButtonImage.size, flipped: false) { rect in
|
||||
newTabButtonImage.draw(in: rect)
|
||||
@@ -714,7 +717,7 @@ fileprivate class WindowButtonsBackdropView: NSView {
|
||||
|
||||
init(window: TerminalWindow) {
|
||||
self.terminalWindow = window
|
||||
self.isLightTheme = window.backgroundColor.isLightColor
|
||||
self.isLightTheme = window.isLightTheme
|
||||
|
||||
super.init(frame: .zero)
|
||||
|
||||
|
@@ -50,7 +50,6 @@ extension Ghostty {
|
||||
var body: some View {
|
||||
let center = NotificationCenter.default
|
||||
let pubZoom = center.publisher(for: Notification.didToggleSplitZoom)
|
||||
let pubEqualize = center.publisher(for: Notification.didEqualizeSplits)
|
||||
|
||||
// If we're zoomed, we don't render anything, we are transparent. This
|
||||
// ensures that the View stays around so we don't lose our state, but
|
||||
@@ -76,7 +75,6 @@ extension Ghostty {
|
||||
container: container
|
||||
)
|
||||
.onReceive(pubZoom) { onZoom(notification: $0) }
|
||||
.onReceive(pubEqualize) { onEqualize(notification: $0) }
|
||||
}
|
||||
}
|
||||
.navigationTitle(surfaceTitle ?? "Ghostty")
|
||||
@@ -137,11 +135,6 @@ extension Ghostty {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func onEqualize(notification: SwiftUI.Notification) {
|
||||
guard case .split(let c) = node else { return }
|
||||
_ = c.equalize()
|
||||
}
|
||||
}
|
||||
|
||||
/// A noSplit leaf node of a split tree.
|
||||
|
@@ -1,4 +1,16 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# This script checks if the build.zig.zon.nix file is up-to-date.
|
||||
# If the `--update` flag is passed, it will update all necessary
|
||||
# files to be up to date.
|
||||
#
|
||||
# The files owned by this are:
|
||||
#
|
||||
# - build.zig.zon.nix
|
||||
# - build.zig.zon.txt
|
||||
# - build.zig.zon2json-lock
|
||||
#
|
||||
# All of these are auto-generated and should not be edited manually.
|
||||
|
||||
# Nothing in this script should fail.
|
||||
set -e
|
||||
@@ -27,9 +39,11 @@ help() {
|
||||
echo ""
|
||||
}
|
||||
|
||||
BUILD_ZIG_ZON="$(realpath "$(dirname "$0")/../../build.zig.zon")"
|
||||
BUILD_ZIG_ZON_LOCK="$(realpath "$(dirname "$0")/../../build.zig.zon2json-lock")"
|
||||
BUILD_ZIG_ZON_NIX="$(realpath "$(dirname "$0")/../../build.zig.zon.nix")"
|
||||
ROOT="$(realpath "$(dirname "$0")/../../")"
|
||||
BUILD_ZIG_ZON="$ROOT/build.zig.zon"
|
||||
BUILD_ZIG_ZON_LOCK="$ROOT/build.zig.zon2json-lock"
|
||||
BUILD_ZIG_ZON_NIX="$ROOT/build.zig.zon.nix"
|
||||
BUILD_ZIG_ZON_TXT="$ROOT/build.zig.zon.txt"
|
||||
|
||||
if [ -f "${BUILD_ZIG_ZON_NIX}" ]; then
|
||||
OLD_HASH=$(sha512sum "${BUILD_ZIG_ZON_NIX}" | awk '{print $1}')
|
||||
@@ -42,7 +56,6 @@ fi
|
||||
rm -f "$BUILD_ZIG_ZON_LOCK"
|
||||
zon2nix "$BUILD_ZIG_ZON" > "$WORK_DIR/build.zig.zon.nix"
|
||||
alejandra --quiet "$WORK_DIR/build.zig.zon.nix"
|
||||
rm -f "$BUILD_ZIG_ZON_LOCK"
|
||||
|
||||
NEW_HASH=$(sha512sum "$WORK_DIR/build.zig.zon.nix" | awk '{print $1}')
|
||||
|
||||
@@ -57,6 +70,7 @@ elif [ "$1" != "--update" ]; then
|
||||
help
|
||||
exit 1
|
||||
else
|
||||
jq -r '.[] .url' "$BUILD_ZIG_ZON_LOCK" | sort > "$BUILD_ZIG_ZON_TXT"
|
||||
mv "$WORK_DIR/build.zig.zon.nix" "$BUILD_ZIG_ZON_NIX"
|
||||
echo -e "\nOK: build.zig.zon.nix updated."
|
||||
exit 0
|
||||
|
27
nix/build-support/fetch-zig-cache.sh
Executable file
27
nix/build-support/fetch-zig-cache.sh
Executable file
@@ -0,0 +1,27 @@
|
||||
#!/bin/sh
|
||||
|
||||
# NOTE THIS IS A TEMPORARY SCRIPT TO SUPPORT PACKAGE MAINTAINERS.
|
||||
#
|
||||
# A future Zig version will hopefully fix the issue where
|
||||
# `zig build --fetch` doesn't fetch transitive dependencies[1]. When that
|
||||
# is resolved, we won't need any special machinery for the general use case
|
||||
# at all and packagers can just use `zig build --fetch`.
|
||||
#
|
||||
# [1]: https://github.com/ziglang/zig/issues/20976
|
||||
|
||||
if [ -z ${ZIG_GLOBAL_CACHE_DIR+x} ]
|
||||
then
|
||||
echo "must set ZIG_GLOBAL_CACHE_DIR!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Go through each line of our build.zig.zon.txt and fetch it.
|
||||
SCRIPT_PATH="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
|
||||
ZON_TXT_FILE="$SCRIPT_PATH/../../build.zig.zon.txt"
|
||||
while IFS= read -r url; do
|
||||
echo "Fetching: $url"
|
||||
zig fetch "$url" >/dev/null 2>&1 || {
|
||||
echo "Failed to fetch: $url" >&2
|
||||
exit 1
|
||||
}
|
||||
done < "$ZON_TXT_FILE"
|
@@ -49,6 +49,7 @@
|
||||
simdutf,
|
||||
zlib,
|
||||
alejandra,
|
||||
jq,
|
||||
minisign,
|
||||
pandoc,
|
||||
hyperfine,
|
||||
@@ -97,6 +98,7 @@ in
|
||||
packages =
|
||||
[
|
||||
# For builds
|
||||
jq
|
||||
llvmPackages_latest.llvm
|
||||
minisign
|
||||
ncurses
|
||||
|
@@ -48,7 +48,7 @@
|
||||
in
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "ghostty";
|
||||
version = "1.1.2";
|
||||
version = "1.1.3";
|
||||
|
||||
# We limit source like this to try and reduce the amount of rebuilds as possible
|
||||
# thus we only provide the source that is needed for the build
|
||||
|
@@ -8,7 +8,7 @@
|
||||
},
|
||||
|
||||
.pixels = .{
|
||||
.url = "git+https://github.com/make-github-pseudonymous-again/pixels?ref=main#d843c2714d32e15b48b8d7eeb480295af537f877",
|
||||
.url = "https://github.com/make-github-pseudonymous-again/pixels/archive/d843c2714d32e15b48b8d7eeb480295af537f877.tar.gz",
|
||||
.hash = "12207ff340169c7d40c570b4b6a97db614fe47e0d83b5801a932dcd44917424c8806",
|
||||
},
|
||||
|
||||
|
@@ -1693,7 +1693,7 @@ pub fn keyCallback(
|
||||
self: *Surface,
|
||||
event: input.KeyEvent,
|
||||
) !InputEffect {
|
||||
// log.debug("text keyCallback event={}", .{event});
|
||||
// log.warn("text keyCallback event={}", .{event});
|
||||
|
||||
// Crash metadata in case we crash in here
|
||||
crash.sentry.thread_state = self.crashThreadState();
|
||||
|
@@ -149,8 +149,17 @@ pub const App = struct {
|
||||
}
|
||||
|
||||
/// Convert a C key event into a Zig key event.
|
||||
///
|
||||
/// The buffer is needed for possibly storing translated UTF-8 text.
|
||||
/// This buffer may (or may not) be referenced by the resulting KeyEvent
|
||||
/// so it should be valid for the lifetime of the KeyEvent.
|
||||
///
|
||||
/// The size of the buffer doesn't need to be large, we always
|
||||
/// used to hardcode 128 bytes and never ran into issues. If it isn't
|
||||
/// large enough an error will be returned.
|
||||
fn coreKeyEvent(
|
||||
self: *App,
|
||||
buf: []u8,
|
||||
target: KeyTarget,
|
||||
event: KeyEvent,
|
||||
) !?input.KeyEvent {
|
||||
@@ -217,7 +226,6 @@ pub const App = struct {
|
||||
// Translate our key using the keymap for our localized keyboard layout.
|
||||
// We only translate for keydown events. Otherwise, we only care about
|
||||
// the raw keycode.
|
||||
var buf: [128]u8 = undefined;
|
||||
const result: input.Keymap.Translation = if (is_down) translate: {
|
||||
// If the event provided us with text, then we use this as a result
|
||||
// and do not do manual translation.
|
||||
@@ -226,7 +234,7 @@ pub const App = struct {
|
||||
.composing = event.composing,
|
||||
.mods = translate_mods,
|
||||
} else try self.keymap.translate(
|
||||
&buf,
|
||||
buf,
|
||||
switch (target) {
|
||||
.app => &self.keymap_state,
|
||||
.surface => |surface| &surface.keymap_state,
|
||||
@@ -360,7 +368,9 @@ pub const App = struct {
|
||||
event: KeyEvent,
|
||||
) !bool {
|
||||
// Convert our C key event into a Zig one.
|
||||
var buf: [128]u8 = undefined;
|
||||
const input_event: input.KeyEvent = (try self.coreKeyEvent(
|
||||
&buf,
|
||||
target,
|
||||
event,
|
||||
)) orelse return false;
|
||||
@@ -1425,7 +1435,9 @@ pub const CAPI = struct {
|
||||
app: *App,
|
||||
event: KeyEvent,
|
||||
) bool {
|
||||
var buf: [128]u8 = undefined;
|
||||
const core_event = app.coreKeyEvent(
|
||||
&buf,
|
||||
.app,
|
||||
event.keyEvent(),
|
||||
) catch |err| {
|
||||
@@ -1677,7 +1689,9 @@ pub const CAPI = struct {
|
||||
surface: *Surface,
|
||||
event: KeyEvent,
|
||||
) bool {
|
||||
var buf: [128]u8 = undefined;
|
||||
const core_event = surface.app.coreKeyEvent(
|
||||
&buf,
|
||||
// Note: this "app" target here looks like a bug, but it is
|
||||
// intentional. coreKeyEvent uses the target only as a way to
|
||||
// trigger preedit callbacks for keymap translation and we don't
|
||||
|
@@ -223,19 +223,6 @@ pub fn init(core_app: *CoreApp, opts: Options) !App {
|
||||
_ = internal_os.setenv("GDK_DISABLE", value[0 .. value.len - 1 :0]);
|
||||
}
|
||||
|
||||
if (version.runtimeAtLeast(4, 14, 0)) {
|
||||
switch (config.@"gtk-gsk-renderer") {
|
||||
.default => {},
|
||||
else => |renderer| {
|
||||
// Force the GSK renderer to a specific value. After GTK 4.14 the
|
||||
// `ngl` renderer is used by default which causes artifacts when
|
||||
// used with Ghostty so it should be avoided.
|
||||
log.warn("setting GSK_RENDERER={s}", .{@tagName(renderer)});
|
||||
_ = internal_os.setenv("GSK_RENDERER", @tagName(renderer));
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
c.gtk_init();
|
||||
const display: *c.GdkDisplay = c.gdk_display_get_default() orelse {
|
||||
// I'm unsure of any scenario where this happens. Because we don't
|
||||
|
@@ -817,16 +817,23 @@ pub fn shouldClose(self: *const Surface) bool {
|
||||
}
|
||||
|
||||
pub fn getContentScale(self: *const Surface) !apprt.ContentScale {
|
||||
const gtk_scale: f32 = scale: {
|
||||
// Future: detect GTK version 4.12+ and use gdk_surface_get_scale so we
|
||||
// can support fractional scaling.
|
||||
const gtk_scale: f32 = @floatFromInt(c.gtk_widget_get_scale_factor(@ptrCast(self.gl_area)));
|
||||
const scale = c.gtk_widget_get_scale_factor(@ptrCast(self.gl_area));
|
||||
if (scale <= 0) {
|
||||
log.warn("gtk_widget_get_scale_factor returned a non-positive number: {d}", .{scale});
|
||||
break :scale 1.0;
|
||||
}
|
||||
break :scale @floatFromInt(scale);
|
||||
};
|
||||
|
||||
// Also scale using font-specific DPI, which is often exposed to the user
|
||||
// via DE accessibility settings (see https://docs.gtk.org/gtk4/class.Settings.html).
|
||||
const xft_dpi_scale = xft_scale: {
|
||||
// gtk-xft-dpi is font DPI multiplied by 1024. See
|
||||
// https://docs.gtk.org/gtk4/property.Settings.gtk-xft-dpi.html
|
||||
const settings = c.gtk_settings_get_default();
|
||||
const settings = c.gtk_settings_get_default() orelse break :xft_scale 1.0;
|
||||
|
||||
var value: c.GValue = std.mem.zeroes(c.GValue);
|
||||
defer c.g_value_unset(&value);
|
||||
@@ -834,11 +841,21 @@ pub fn getContentScale(self: *const Surface) !apprt.ContentScale {
|
||||
c.g_object_get_property(@ptrCast(@alignCast(settings)), "gtk-xft-dpi", &value);
|
||||
const gtk_xft_dpi = c.g_value_get_int(&value);
|
||||
|
||||
// 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
|
||||
// ensure that the scale is never negative
|
||||
if (gtk_xft_dpi <= 0) {
|
||||
log.warn("gtk-xft-dpi was not set, using default value", .{});
|
||||
break :xft_scale 1.0;
|
||||
}
|
||||
|
||||
// As noted above gtk-xft-dpi is multiplied by 1024, so we divide by
|
||||
// 1024, then divide by the default value (96) to derive a scale. Note
|
||||
// gtk-xft-dpi can be fractional, so we use floating point math here.
|
||||
const xft_dpi: f32 = @as(f32, @floatFromInt(gtk_xft_dpi)) / 1024;
|
||||
break :xft_scale xft_dpi / 96;
|
||||
const xft_dpi: f32 = @as(f32, @floatFromInt(gtk_xft_dpi)) / 1024.0;
|
||||
break :xft_scale xft_dpi / 96.0;
|
||||
};
|
||||
|
||||
const scale = gtk_scale * xft_dpi_scale;
|
||||
@@ -1325,14 +1342,35 @@ fn gtkRealize(area: *c.GtkGLArea, ud: ?*anyopaque) callconv(.C) void {
|
||||
/// This is called when the underlying OpenGL resources must be released.
|
||||
/// This is usually due to the OpenGL area changing GDK surfaces.
|
||||
fn gtkUnrealize(area: *c.GtkGLArea, ud: ?*anyopaque) callconv(.C) void {
|
||||
_ = area;
|
||||
|
||||
log.debug("gl surface unrealized", .{});
|
||||
const self = userdataSelf(ud.?);
|
||||
self.core_surface.renderer.displayUnrealized();
|
||||
log.debug("gl surface unrealized", .{});
|
||||
|
||||
// See gtkRealize for why we do this here.
|
||||
c.gtk_im_context_set_client_widget(self.im_context, null);
|
||||
|
||||
// There is no guarantee that our GLArea context is current
|
||||
// when unrealize is emitted, so we need to make it current.
|
||||
c.gtk_gl_area_make_current(area);
|
||||
if (c.gtk_gl_area_get_error(area)) |err| {
|
||||
// I don't know a scenario this can happen, but it means
|
||||
// we probably leaked memory because displayUnrealized
|
||||
// below frees resources that aren't specifically OpenGL
|
||||
// related. I didn't make the OpenGL renderer handle this
|
||||
// scenario because I don't know if its even possible
|
||||
// under valid circumstances, so let's log.
|
||||
const message: []const u8 = if (err.*.message) |v|
|
||||
std.mem.span(v)
|
||||
else
|
||||
"(no message)";
|
||||
log.warn(
|
||||
"gl_area_make_current failed in unrealize msg={s}",
|
||||
.{message},
|
||||
);
|
||||
log.warn("OpenGL resources and memory likely leaked", .{});
|
||||
return;
|
||||
} else {
|
||||
self.core_surface.renderer.displayUnrealized();
|
||||
}
|
||||
}
|
||||
|
||||
/// render signal
|
||||
@@ -1914,6 +1952,14 @@ fn gtkInputPreeditChanged(
|
||||
) callconv(.C) void {
|
||||
const self = userdataSelf(ud.?);
|
||||
|
||||
// Any preedit change should mark that we're composing. Its possible this
|
||||
// is false using fcitx5-hangul and typing "dkssud<space>" ("안녕"). The
|
||||
// second "s" results in a "commit" for "안" which sets composing to false,
|
||||
// but then immediately sends a preedit change for the next symbol. With
|
||||
// composing set to false we won't commit this text. Therefore, we must
|
||||
// ensure it is set here.
|
||||
self.im_composing = true;
|
||||
|
||||
// Get our pre-edit string that we'll use to show the user.
|
||||
var buf: [*c]u8 = undefined;
|
||||
_ = c.gtk_im_context_get_preedit_string(ctx, &buf, null, null);
|
||||
|
@@ -596,6 +596,10 @@ pub fn focusCurrentTab(self: *Window) void {
|
||||
const surface = tab.focus_child orelse return;
|
||||
const gl_area = @as(*c.GtkWidget, @ptrCast(surface.gl_area));
|
||||
_ = c.gtk_widget_grab_focus(gl_area);
|
||||
|
||||
if (surface.getTitle()) |title| {
|
||||
self.setTitle(title);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn onConfigReloaded(self: *Window) void {
|
||||
|
@@ -48,4 +48,18 @@ window.ssd.no-border-radius {
|
||||
.terminal-window .notebook separator {
|
||||
background-color: rgba(250, 250, 250, 1);
|
||||
background-clip: content-box;
|
||||
|
||||
/* This works around the oversized drag area for the right side of GtkPaned.
|
||||
*
|
||||
* Upstream Gtk issue:
|
||||
* https://gitlab.gnome.org/GNOME/gtk/-/issues/4484#note_2362002
|
||||
*
|
||||
* Ghostty issue:
|
||||
* https://github.com/ghostty-org/ghostty/issues/3020
|
||||
*
|
||||
* Without this, it's not possible to select the first character on the
|
||||
* right-hand side of a split.
|
||||
*/
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
@@ -19,7 +19,7 @@ const GitVersion = @import("GitVersion.zig");
|
||||
/// TODO: When Zig 0.14 is released, derive this from build.zig.zon directly.
|
||||
/// Until then this MUST match build.zig.zon and should always be the
|
||||
/// _next_ version to release.
|
||||
const app_version: std.SemanticVersion = .{ .major = 1, .minor = 1, .patch = 2 };
|
||||
const app_version: std.SemanticVersion = .{ .major = 1, .minor = 1, .patch = 3 };
|
||||
|
||||
/// Standard build configuration options.
|
||||
optimize: std.builtin.OptimizeMode,
|
||||
@@ -70,8 +70,10 @@ pub fn init(b: *std.Build) !Config {
|
||||
|
||||
// If we're building for macOS and we're on macOS, we need to
|
||||
// use a generic target to workaround compilation issues.
|
||||
if (result.result.os.tag == .macos and builtin.target.isDarwin()) {
|
||||
result = genericMacOSTarget(b, null);
|
||||
if (result.result.os.tag == .macos and
|
||||
builtin.target.os.tag.isDarwin())
|
||||
{
|
||||
result = genericMacOSTarget(b, result.query.cpu_arch);
|
||||
}
|
||||
|
||||
// If we have no minimum OS version, we set the default based on
|
||||
|
@@ -2089,13 +2089,11 @@ keybind: Keybinds = .{},
|
||||
/// debug builds, `false` for all others.
|
||||
@"gtk-opengl-debug": bool = builtin.mode == .Debug,
|
||||
|
||||
/// After GTK 4.14.0, we need to force the GSK renderer to OpenGL as the default
|
||||
/// GSK renderer is broken on some systems. If you would like to override
|
||||
/// that bekavior, set `gtk-gsk-renderer=default` and either use your system's
|
||||
/// default GSK renderer, or set the GSK_RENDERER environment variable to your
|
||||
/// renderer of choice before launching Ghostty. This setting has no effect when
|
||||
/// using versions of GTK earlier than 4.14.0.
|
||||
@"gtk-gsk-renderer": GtkGskRenderer = .opengl,
|
||||
/// Obsolete configuration that should not be set. This was deprecated in
|
||||
/// Ghostty 1.1.3 and no longer has any effect. The configuration key will
|
||||
/// be fully removed in 1.2.0. You can manually override the GSK renderer
|
||||
/// using standard environment variables such as `GSK_RENDERER` (from GTK).
|
||||
@"gtk-gsk-renderer": GtkGskRenderer = .default,
|
||||
|
||||
/// If `true`, the Ghostty GTK application will run in single-instance mode:
|
||||
/// each new `ghostty` process launched will result in a new window if there is
|
||||
@@ -2580,7 +2578,7 @@ pub fn default(alloc_gpa: Allocator) Allocator.Error!Config {
|
||||
);
|
||||
try result.keybind.set.put(
|
||||
alloc,
|
||||
.{ .key = .{ .translated = .equal }, .mods = .{ .super = true, .ctrl = true, .shift = true } },
|
||||
.{ .key = .{ .translated = .plus }, .mods = .{ .super = true, .ctrl = true, .shift = true } },
|
||||
.{ .equalize_splits = {} },
|
||||
);
|
||||
|
||||
|
@@ -1019,6 +1019,10 @@ pub fn setFontGrid(self: *Metal, grid: *font.SharedGrid) void {
|
||||
// out a better way to handle this.
|
||||
log.err("error resizing cells buffer err={}", .{err});
|
||||
};
|
||||
|
||||
// Reset our viewport to force a rebuild, since `setScreenSize` only
|
||||
// does this when the number of cells changes, which isn't guaranteed.
|
||||
self.cells_viewport = null;
|
||||
}
|
||||
|
||||
/// Update the frame data.
|
||||
|
@@ -47,7 +47,19 @@ made available for use as modules by way of `use <filename>`.
|
||||
Ghostty launches Elvish, passing the environment with `XDG_DATA_DIRS`prepended
|
||||
with `$GHOSTTY_RESOURCES_DIR/src/shell-integration`. It contains
|
||||
`./elvish/lib/ghostty-integration.elv`. The user can then import it
|
||||
by `use ghostty-integration`, which will run the integration routines.
|
||||
by `use ghostty-integration` every time after shell startup or
|
||||
autostart integration in `$XDG_CONFIG_HOME/elvish/rc.elv`,
|
||||
which will run the integration routines.
|
||||
|
||||
If you decide to autostart `ghostty-integration` with `rc.elv`, you should
|
||||
detect whether the terminal is Ghostty or not. To do this, add this to the end
|
||||
of your `rc.elv` file:
|
||||
|
||||
```elvish
|
||||
if (eq $E:TERM "xterm-ghostty") {
|
||||
use ghostty-integration
|
||||
}
|
||||
```
|
||||
|
||||
The [Elvish](https://elv.sh) shell integration is supported by
|
||||
the community and is not officially supported by Ghostty. We distribute
|
||||
|
@@ -92,7 +92,7 @@
|
||||
}
|
||||
|
||||
if (not $sudoedit) { set args = [ TERMINFO=$E:TERMINFO $@args ] }
|
||||
command sudo $@args
|
||||
(external sudo) $@args
|
||||
}
|
||||
|
||||
defer {
|
||||
|
@@ -86,7 +86,9 @@ pub const Action = union(enum) {
|
||||
final: u8,
|
||||
|
||||
/// The list of separators used for CSI params. The value of the
|
||||
/// bit can be mapped to Sep.
|
||||
/// bit can be mapped to Sep. The index of this bit set specifies
|
||||
/// the separator AFTER that param. For example: 0;4:3 would have
|
||||
/// index 1 set.
|
||||
pub const SepList = std.StaticBitSet(MAX_PARAMS);
|
||||
|
||||
/// The separator used for CSI params.
|
||||
@@ -192,7 +194,19 @@ pub const Action = union(enum) {
|
||||
/// 4 because we also use the intermediates array for UTF8 decoding which
|
||||
/// can be at most 4 bytes.
|
||||
const MAX_INTERMEDIATE = 4;
|
||||
const MAX_PARAMS = 16;
|
||||
|
||||
/// Maximum number of CSI parameters. This is arbitrary. Practically, the
|
||||
/// only CSI command that uses more than 3 parameters is the SGR command
|
||||
/// which can be infinitely long. 24 is a reasonable limit based on empirical
|
||||
/// data. This used to be 16 but Kakoune has a SGR command that uses 17
|
||||
/// parameters.
|
||||
///
|
||||
/// We could in the future make this the static limit and then allocate after
|
||||
/// but that's a lot more work and practically its so rare to exceed this
|
||||
/// number. I implore TUI authors to not use more than this number of CSI
|
||||
/// params, but I suspect we'll introduce a slow path with heap allocation
|
||||
/// one day.
|
||||
const MAX_PARAMS = 24;
|
||||
|
||||
/// Current state of the state machine
|
||||
state: State = .ground,
|
||||
@@ -689,6 +703,64 @@ test "csi: SGR mixed colon and semicolon with blank" {
|
||||
}
|
||||
}
|
||||
|
||||
// This is from a Kakoune actual SGR sequence also.
|
||||
test "csi: SGR mixed colon and semicolon setting underline, bg, fg" {
|
||||
var p = init();
|
||||
_ = p.next(0x1B);
|
||||
for ("[4:3;38;2;51;51;51;48;2;170;170;170;58;2;255;97;136") |c| {
|
||||
const a = p.next(c);
|
||||
try testing.expect(a[0] == null);
|
||||
try testing.expect(a[1] == null);
|
||||
try testing.expect(a[2] == null);
|
||||
}
|
||||
|
||||
{
|
||||
const a = p.next('m');
|
||||
try testing.expect(p.state == .ground);
|
||||
try testing.expect(a[0] == null);
|
||||
try testing.expect(a[1].? == .csi_dispatch);
|
||||
try testing.expect(a[2] == null);
|
||||
|
||||
const d = a[1].?.csi_dispatch;
|
||||
try testing.expect(d.final == 'm');
|
||||
try testing.expectEqual(17, d.params.len);
|
||||
try testing.expectEqual(@as(u16, 4), d.params[0]);
|
||||
try testing.expect(d.params_sep.isSet(0));
|
||||
try testing.expectEqual(@as(u16, 3), d.params[1]);
|
||||
try testing.expect(!d.params_sep.isSet(1));
|
||||
try testing.expectEqual(@as(u16, 38), d.params[2]);
|
||||
try testing.expect(!d.params_sep.isSet(2));
|
||||
try testing.expectEqual(@as(u16, 2), d.params[3]);
|
||||
try testing.expect(!d.params_sep.isSet(3));
|
||||
try testing.expectEqual(@as(u16, 51), d.params[4]);
|
||||
try testing.expect(!d.params_sep.isSet(4));
|
||||
try testing.expectEqual(@as(u16, 51), d.params[5]);
|
||||
try testing.expect(!d.params_sep.isSet(5));
|
||||
try testing.expectEqual(@as(u16, 51), d.params[6]);
|
||||
try testing.expect(!d.params_sep.isSet(6));
|
||||
try testing.expectEqual(@as(u16, 48), d.params[7]);
|
||||
try testing.expect(!d.params_sep.isSet(7));
|
||||
try testing.expectEqual(@as(u16, 2), d.params[8]);
|
||||
try testing.expect(!d.params_sep.isSet(8));
|
||||
try testing.expectEqual(@as(u16, 170), d.params[9]);
|
||||
try testing.expect(!d.params_sep.isSet(9));
|
||||
try testing.expectEqual(@as(u16, 170), d.params[10]);
|
||||
try testing.expect(!d.params_sep.isSet(10));
|
||||
try testing.expectEqual(@as(u16, 170), d.params[11]);
|
||||
try testing.expect(!d.params_sep.isSet(11));
|
||||
try testing.expectEqual(@as(u16, 58), d.params[12]);
|
||||
try testing.expect(!d.params_sep.isSet(12));
|
||||
try testing.expectEqual(@as(u16, 2), d.params[13]);
|
||||
try testing.expect(!d.params_sep.isSet(13));
|
||||
try testing.expectEqual(@as(u16, 255), d.params[14]);
|
||||
try testing.expect(!d.params_sep.isSet(14));
|
||||
try testing.expectEqual(@as(u16, 97), d.params[15]);
|
||||
try testing.expect(!d.params_sep.isSet(15));
|
||||
try testing.expectEqual(@as(u16, 136), d.params[16]);
|
||||
try testing.expect(!d.params_sep.isSet(16));
|
||||
}
|
||||
}
|
||||
|
||||
test "csi: colon for non-m final" {
|
||||
var p = init();
|
||||
_ = p.next(0x1B);
|
||||
|
@@ -103,14 +103,18 @@ pub const Parser = struct {
|
||||
|
||||
/// Next returns the next attribute or null if there are no more attributes.
|
||||
pub fn next(self: *Parser) ?Attribute {
|
||||
if (self.idx > self.params.len) return null;
|
||||
|
||||
// Implicitly means unset
|
||||
if (self.params.len == 0) {
|
||||
if (self.idx >= self.params.len) {
|
||||
// If we're at index zero it means we must have an empty
|
||||
// list and an empty list implicitly means unset.
|
||||
if (self.idx == 0) {
|
||||
// Add one to ensure we don't loop on unset
|
||||
self.idx += 1;
|
||||
return .unset;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
const slice = self.params[self.idx..self.params.len];
|
||||
const colon = self.params_sep.isSet(self.idx);
|
||||
self.idx += 1;
|
||||
@@ -788,7 +792,6 @@ test "sgr: direct fg colon with colorspace and extra param" {
|
||||
|
||||
{
|
||||
const v = p.next().?;
|
||||
std.log.warn("WHAT={}", .{v});
|
||||
try testing.expect(v == .direct_color_fg);
|
||||
try testing.expectEqual(@as(u8, 1), v.direct_color_fg.r);
|
||||
try testing.expectEqual(@as(u8, 2), v.direct_color_fg.g);
|
||||
@@ -864,3 +867,50 @@ test "sgr: kakoune input" {
|
||||
|
||||
//try testing.expect(p.next() == null);
|
||||
}
|
||||
|
||||
// Discussion #5930, another input sent by kakoune
|
||||
test "sgr: kakoune input issue underline, fg, and bg" {
|
||||
// echo -e "\033[4:3;38;2;51;51;51;48;2;170;170;170;58;2;255;97;136mset everything in one sequence, broken\033[m"
|
||||
|
||||
// This used to crash
|
||||
var p: Parser = .{
|
||||
.params = &[_]u16{ 4, 3, 38, 2, 51, 51, 51, 48, 2, 170, 170, 170, 58, 2, 255, 97, 136 },
|
||||
.params_sep = sep: {
|
||||
var list = SepList.initEmpty();
|
||||
list.set(0);
|
||||
break :sep list;
|
||||
},
|
||||
};
|
||||
|
||||
{
|
||||
const v = p.next().?;
|
||||
try testing.expect(v == .underline);
|
||||
try testing.expectEqual(Attribute.Underline.curly, v.underline);
|
||||
}
|
||||
|
||||
{
|
||||
const v = p.next().?;
|
||||
try testing.expect(v == .direct_color_fg);
|
||||
try testing.expectEqual(@as(u8, 51), v.direct_color_fg.r);
|
||||
try testing.expectEqual(@as(u8, 51), v.direct_color_fg.g);
|
||||
try testing.expectEqual(@as(u8, 51), v.direct_color_fg.b);
|
||||
}
|
||||
|
||||
{
|
||||
const v = p.next().?;
|
||||
try testing.expect(v == .direct_color_bg);
|
||||
try testing.expectEqual(@as(u8, 170), v.direct_color_bg.r);
|
||||
try testing.expectEqual(@as(u8, 170), v.direct_color_bg.g);
|
||||
try testing.expectEqual(@as(u8, 170), v.direct_color_bg.b);
|
||||
}
|
||||
|
||||
{
|
||||
const v = p.next().?;
|
||||
try testing.expect(v == .underline_color);
|
||||
try testing.expectEqual(@as(u8, 255), v.underline_color.r);
|
||||
try testing.expectEqual(@as(u8, 97), v.underline_color.g);
|
||||
try testing.expectEqual(@as(u8, 136), v.underline_color.b);
|
||||
}
|
||||
|
||||
try testing.expect(p.next() == null);
|
||||
}
|
||||
|
@@ -932,7 +932,7 @@ pub fn Stream(comptime Handler: type) type {
|
||||
// SGR - Select Graphic Rendition
|
||||
'm' => switch (input.intermediates.len) {
|
||||
0 => if (@hasDecl(T, "setAttribute")) {
|
||||
// log.info("parse SGR params={any}", .{action.params});
|
||||
// log.info("parse SGR params={any}", .{input.params});
|
||||
var p: sgr.Parser = .{
|
||||
.params = input.params,
|
||||
.params_sep = input.params_sep,
|
||||
|
@@ -220,7 +220,7 @@ pub fn init(self: *Termio, alloc: Allocator, opts: termio.Options) !void {
|
||||
.renderer_mailbox = opts.renderer_mailbox,
|
||||
.surface_mailbox = opts.surface_mailbox,
|
||||
.size = opts.size,
|
||||
.backend = opts.backend,
|
||||
.backend = backend,
|
||||
.mailbox = opts.mailbox,
|
||||
.terminal_stream = .{
|
||||
.handler = handler,
|
||||
|
@@ -1418,11 +1418,13 @@ pub const StreamHandler = struct {
|
||||
var buf = std.ArrayList(u8).init(self.alloc);
|
||||
defer buf.deinit();
|
||||
const writer = buf.writer();
|
||||
try writer.writeAll("\x1b]21");
|
||||
|
||||
for (request.list.items) |item| {
|
||||
switch (item) {
|
||||
.query => |key| {
|
||||
// If the writer buffer is empty, we need to write our prefix
|
||||
if (buf.items.len == 0) try writer.writeAll("\x1b]21");
|
||||
|
||||
const color: terminal.color.RGB = switch (key) {
|
||||
.palette => |palette| self.terminal.color_palette.colors[palette],
|
||||
.special => |special| switch (special) {
|
||||
@@ -1517,14 +1519,16 @@ pub const StreamHandler = struct {
|
||||
}
|
||||
}
|
||||
|
||||
// If we had any writes to our buffer, we queue them now
|
||||
if (buf.items.len > 0) {
|
||||
try writer.writeAll(request.terminator.string());
|
||||
|
||||
self.messageWriter(.{
|
||||
.write_alloc = .{
|
||||
.alloc = self.alloc,
|
||||
.data = try buf.toOwnedSlice(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Note: we don't have to do a queueRender here because every
|
||||
// processed stream will queue a render once it is done processing
|
||||
|
Reference in New Issue
Block a user