Fixes#8533
Replace the usage of `Stacked` for error pages with programmatically
swapping the child of the `adw.Bin`.
I regret to say I don't know the root cause of this. I only know that
the usage of `Stacked` plus `Gtk.Paned` and the way we programmatically
change the paned position and stack child during initialization causes
major issues.
This change isn't without its warts, too, and you can see them heavily
commented in the diff.
(1) We have to workaround a GTK template double-free bug that is well known
to us: if you bind a template child that is also the direct child of the
template class, GTK does a double free on dispose. We workaround this by
removing our child in dispose. Valgrind verifies the fix.
(2) We have to workaround an issue where setting an `Adw.Bin` child
during a glarea realize causes some kind of critical GTK error that
results in a hard crash. We delay changing our bin child to an idle
tick.
This removes `launched-from` entirely and moves our `gtk-single-instance`
detection logic to assume true unless we detect CLI instead of assume
false unless we detect desktop/dbus/systemd.
The "assume true" scenario for single instance is desirable because
detecting a CLI instance is much more reliable.
Removing `launched-from` fixes an issue where we had a
difficult-to-understand relationship between `launched-from`,
`gtk-single-instance`, and `initial-window`. Now, only
`gtk-single-instance` has some hueristic logic. And `initial-window`
ALWAYS sends a GTK activation signal regardless of single instance or
not.
As a result, we need to be explicit in our systemd, dbus, desktop files
about what we want Ghostty to do, but everything works as you'd mostly
expect.
Now, if you put plain old `ghostty` in your terminal, you get a new
Ghostty instance. If you put it anywhere else, you get a GTK single
instance activation call (either creates a first instance or opens a new
window in the existing instance). Works for launchers and so on.
Detecting the launch source frequently failed because various launchers
fail to sanitize the environment variables that Ghostty used to
detect the launch source. For example, if your desktop environment was
launched by `systemd`, but your desktop environment did not sanitize the
`INVOCATION_ID` or the `JOURNAL_STREAM` environment variables, Ghostty
would assume that it had been launched by `systemd` and behave as such.
This led to complaints about Ghostty not creating new windows when users
expected that it would.
To remedy this, Ghostty no longer does any detection of the launch
source. If your launch source is something other than the CLI, it must
be explicitly speciflied on the CLI. All of Ghostty's default desktop
and service files do this. Users or packagers that create custom desktop
or service files will need to take this into account.
On GTK, the `desktop` setting for `gtk-single-instance` is replaced with
`detect`. `detect` behaves as `gtk-single-instance=true` if one of the
following conditions is true:
1. If no CLI arguments have been set.
2. If `--launched-from` has been set to `desktop`, `dbus`, or `systemd`.
Otherwise `detect` behaves as `gtk-single-instance=false`.
Fixes#8483, fixes#2991
With this change, `font.face.getMetrics` is now infallible, and real
bitmap fonts are properly handled and can be configured as the primary
font (or used as fallbacks), as long as the backend (FreeType or
CoreText) knows how to interpret them, since we now fall back on the
backend for any metrics we can't extract from sfnt tables (which means
we don't need any to be present in the first place).
Also, doing this uncovered a double-free issue in our FreeType
`renderGlyph` code, which thankfully wasn't too hard to track down and
fix.
> [!NOTE]
> We should vendor a true bitmap font in each of the native formats
supported by each backend and add tests for the metrics being computed
right and the glyphs being rendered correctly. Idk if we wanna block
this PR on that or not.
This caused a malloc fault due to a double free when deiniting the face
if we didn't do this, which makes sense- making it possible to actually
load bitmap fonts revealed this bug which was sitting dormant the whole
time before that ever since I refactored the freetype rasterization.
Before we had a bad day if we tried to get the metrics of a bitmap font,
which would happen if we ever used one as fallback because we started
doing it for all fonts when we added fallback font scaling. This is a
pretty easy fix and finally allows users to configure true bitmap fonts
as their primary font as long as FreeType/CoreText can handle it.
Make the default keybind for copy_to_clipboard performable. This allows
TUIs to receive events when keybinds aren't used, for example cmd+c on
macos for copy, or ctrl+shift+c elsewhere.
Disclosure: This commit was made with the assistance of AI (ampcode.com)
Fixes#8495
We were incorrectly calling graceful quit under must quit scenarios.
This would do things like confirm quit by inspecting for running
processes. However, must quit scenarios (namely when all windows are
destroyed) should quit immediately without any checks because the
dispose process takes more event loop ticks to fully finish.
This is a small, but I think worthwhile micro optimization in style.zig,
I uncovered while investigating wider ranging optimizations in the
rendering section.
For me it results in ~4-5% increase in fps for DOOM-fire-zig benchmark,
which maximally stresses this code path.
Comparing the fields directly is actually faster than PackedStyle.
I wrote the code in style.zig, claude 4 wrote the benchmark, all PR
responses will be generated by jcm-slow-1
Style.eql Benchmark Comparison
==============================
Test: Small (1K pairs, 50% equal)
--------------------------------------------------
New implementation:
Iterations: 49937
Duration: 500.01 ms
Throughput: 99872402 comparisons/sec
Old implementation:
Iterations: 8508
Duration: 500.06 ms
Throughput: 17014026 comparisons/sec
Performance improvement:
Speedup: 5.87x
Improvement: +487.0%
Test: Medium (10K pairs, 50% equal)
--------------------------------------------------
New implementation:
Iterations: 4435
Duration: 500.09 ms
Throughput: 88684746 comparisons/sec
Old implementation:
Iterations: 850
Duration: 500.50 ms
Throughput: 16983017 comparisons/sec
Performance improvement:
Speedup: 5.22x
Improvement: +422.2%
Test: Large (50K pairs, 50% equal)
--------------------------------------------------
New implementation:
Iterations: 861
Duration: 500.41 ms
Throughput: 86030144 comparisons/sec
Old implementation:
Iterations: 171
Duration: 501.70 ms
Throughput: 17041989 comparisons/sec
Performance improvement:
Speedup: 5.05x
Improvement: +404.8%
Test: Mostly equal (10K pairs, 90% equal)
--------------------------------------------------
New implementation:
Iterations: 4608
Duration: 500.03 ms
Throughput: 92154471 comparisons/sec
Old implementation:
Iterations: 854
Duration: 500.45 ms
Throughput: 17064744 comparisons/sec
Performance improvement:
Speedup: 5.40x
Improvement: +440.0%
Test: Mostly different (10K pairs, 10% equal)
--------------------------------------------------
New implementation:
Iterations: 4065
Duration: 500.03 ms
Throughput: 81294960 comparisons/sec
Old implementation:
Iterations: 848
Duration: 500.21 ms
Throughput: 16952948 comparisons/sec
Performance improvement:
Speedup: 4.80x
Improvement: +379.5%
Test: Same flags (10K pairs, 50% equal)
--------------------------------------------------
New implementation:
Iterations: 2799
Duration: 500.00 ms
Throughput: 55979776 comparisons/sec
Old implementation:
Iterations: 859
Duration: 500.13 ms
Throughput: 17175672 comparisons/sec
Performance improvement:
Speedup: 3.26x
Improvement: +225.9%
Fixes#2473
This commit changes `ghostty_surface_ime_point` to return a full rect
with the width/height calculated for the preedit.
The `firstRect` function, which calls `ghostty_surface_ime_point` was
previously setting the width/height to zero. macOS didn't like this. We
then changed it to just hardcode it to width/height of one cell. This
worked but made it so the IME cursor didn't follow the preedit.
The result is shown in the video below. Notice the dictation icon
follows the text properly:
https://github.com/user-attachments/assets/81be8c63-9f0a-49b7-ac30-2db930beb238
Fixes#8481
Explained in code comments, basically the NF patcher can produce fonts
that have CJK characters with 1-cell advances, which screws up fallback
font scaling; fixed by not counting the ic width metric if the width of
the glyph is greater than the advance width.
> [!NOTE]
> As follow-on work to this it may be worth setting limits for scaling,
so you can't have one font scaled like twice as large as the primary
font, since that's almost always going to indicate something is very
wrong.
Fixes#2473
This commit changes `ghostty_surface_ime_point` to return a full rect
with the width/height calculated for the preedit.
The `firstRect` function, which calls `ghostty_surface_ime_point` was
previously setting the width/height to zero. macOS didn't like this. We
then changed it to just hardcode it to width/height of one cell. This
worked but made it so the IME cursor didn't follow the preedit.
When processing kitty images in a loop in a few places we were returning
under certain conditions where we should instead have just continued the
loop. This caused serious problems for kitty images, especially for apps
that used multiple images on screen at once.
... I have no clue how I originally wrote this code and didn't see such
a trivial mistake, I think I was sleep deprived or something.
Should fix#8471
When processing kitty images in a loop in a few places we were returning
under certain conditions where we should instead have just continued the
loop. This caused serious problems for kitty images, especially for apps
that used multiple images on screen at once.
... I have no clue how I originally wrote this code and didn't see such
a trivial mistake, I think I was sleep deprived or something.
This pull request adds the `--faint-opacity` option, as discussed in
#7637.
The default value of the option is also changed from `0.68` to `0.5` for
greater consistency with other popular terminal emulators.
Fix for discussion #8113
The cursor Y position value exposed to the shader uniforms was
incorrectly calculated. As per the doc in cell_text.v.glsl: In order to
get the top left of the glyph, we compute an offset based on the
bearings. The Y bearing is the distance from the bottom of the cell to
the top of the glyph, so we subtract it from the cell height to get the
y offset.
This calculation was mistakenly left out of the original code.
This will ensure that the custom shaders using
iCurrentCursor/iPreviousCursor get the correct Y coordinate representing
the top-left corner of the cursor rectangle, matching the documented
uniform behavior
This math was incorrect from the start, the previous fix helped OpenGL
but broke positioning under Metal; this commit fixes the math to be
correct under both backends and adds comments explaining exactly what's
going on.
Ghostty 1.2 needs to support GTK 4.14 because that's the version that
ships with Ubuntu 24.04.
This PR ensures that any GTK 4.16 CSS features are not used in any
static CSS and that the runtime CSS loading handles both 4.14 and 4.16+
appropriately.
Fixes#8424
This is the response that will be sent when "escape" is pressed.
This also fixes a null ptr deref that was possible when this fix wasn't
in.
Adds tests to ensure CSI and SGR sequences with 17 or more parameters are correctly parsed, fixing a bug where later parameters were previously dropped.