I haven't worked with GTK, but what you are describing here sounds reminiscent of what we have been dealing with trying to build Godot bindings in Zig with a nice API. the project is in mid-flight, but Godot:
- has tons of OOP concepts: classes, virtual methods, properties, signals, etc
- a C API to work with all of those concepts, define your own objects, properties, and so on
- manages the lifetimes of any engine objects (you can attach userdata to any of them)
- a whole tree of reference counted objects
it's a huge headache trying to figure out how to tie it into Zig idioms in a way that is an optimal API (specifically, dealing with lifetimes). we've come pretty far, but I am wondering if you have any additional insights or code snippets I should look at.
also.. now I want to attempt to write a Ghostty frontend as a Godot extension
Fraterkes 4 hours ago [-]
Thx for the work you're doing! Just out of curiosity, I sometimes struggle to write performant C# Godot code because it's hard to interface with the engine without doing a lot of back and forth conversions to engine types. You end up doing a lot of allocations. Did you run into that kind of stuff while creating your bindings?
aidenn0 9 hours ago [-]
Hopefully it's improved, but the last time I wrote a GTK binding for a language, it was miserable. 98% of it was sane, but the remaining 2% had things like "whether or not this function takes a reference to this object depends on the other parameters passed" which made liveness analysis "interesting."
DanielHB 4 hours ago [-]
This is what people mean when they say "make invalid states unrepresentable", languages with union types can easily avoid this problem.
biorach 3 hours ago [-]
It doesn't sound like they are talking about invalid states, more like they are taking about the kind of thing that in Rust would be represented by `Option<Box<dyn SomeTrait>>` or suchlike. Maybe your point is that in Rust much less ceremony is necessary to avoid hitting a null pointer when doing this. But still, in either language it's easy to end up with hard to follow logic when doing this.
DanielHB 2 hours ago [-]
not super familiar with Rust but isn't Option<T> just an union type of null and T? I get the language has special semantics for this compared to a union type but it is conceptionally just an union.
For example this is something you can do with typescript.
function(args: Arguments) { ... }
type Arguments = { a: number, b: number } | { a: number, b: string, c: number }
the Arguments { a: 1, b: 1, c: 1 } is not representable.
poetril 9 hours ago [-]
I did not know this was a project that was in progress, and its quite exciting. I love Godot, and am quite fond a Zig as well. I'll be keeping my eye on this.
crawshaw 14 hours ago [-]
Nice example of how good programming is often about meeting systems where they are:
Whatever your feelings are about OOP and memory management, the reality is that if you choose GTK, you're forced into interfacing in some way with the GObject type system. You can't avoid it.
Well you can avoid it and we did avoid it. And it leads to a mess trying to tie the lifetimes of your non-reference-counted objects to the reference counted ones. There was an entire class of bug that kept popping up in the Ghostty GTK application that could basically be summed up as: the Zig memory or the GTK memory has been freed, but not both.
giancarlostoro 57 minutes ago [-]
GTK having this kind of scheme is why Vala was made and inspired by C# but uses GObject and all its joys, then transpiles your code to C.
This is why a surprising number of GTK applications (more than I realized) are coded in Vala. I lowkey wish they had just adopted D instead of building up Vala. D is basically compiled C# to me in its own ways.
eviks 8 hours ago [-]
Giving in a bad system is more pragmatic rather than good
flohofwoe 5 hours ago [-]
Careful what you wish for. These days one has to be thankful if a badly designed old system isn't replaced with a new system that's even worse despite the best intentions ;)
hnlmorg 5 hours ago [-]
The two terms aren’t mutually exclusive
eviks 5 hours ago [-]
Only in a dictionary. In a sentence that has the context of a poorly designed system, they are because you explicitly have to do worse programming to meet the system at a worse point
hnlmorg 5 hours ago [-]
“Good” and “bad” are subjective.
Being pragmatic about the design of an ecosystem and working with it, could be seen as good programming vs the alternative of fighting that ecosystem and thus creating entirely new classes of bugs.
And this was what the GP was responding to. They were was that the pragmatism of working with that ecosystem showed good judgement.
Lerc 14 hours ago [-]
>Whatever your feelings are about OOP and memory management, the reality is that if you choose GTK, you're forced into interfacing in some way with the GObject type system. You can't avoid it.
In the past this has also been my assessment of GTK. It lead me to decide to take the other path, to never directly use GTK. I appreciate the value in having a unified user interface between applications, but I have always thought the features that GTK provides were not worth the penalties paid. I have worked around the edges of GTK in open source apps that are GTK based. That lead me to think that GTK and the GObject system is opinionated in a way that are not terribly compatible with my own opinions.
I don't hate that GTK exists, It is my choice not to use it and I am fine with that. However I also have encountered people who seem to think it is not my choice not to use it. There are a million and one other GUI toolkits out there, of which GTK is one of the most polished. I can't shake the feeling that if GTK were less dominant, some of the resources that go to polishing GTK might have been spent polishing a different framework with a nicer underlying architecture.
Of course what I consider nicer might not be what others consider nicer. Of those who use GTK, how many use it begrudgingly, and how many feel like it is the best tool for the job?
mitchellh 14 hours ago [-]
> That lead me to think that GTK and the GObject system is opinionated in a way that are not terribly compatible with my own opinions.
This might be amusing for me to say but... I also feel this way. I disagree a lot with the Gnome ecosystem's point of view. Funny!
Using GTK for Linux was a pragmatic choice. A goal of Ghostty is to be "platform-native" (defined here because there's no such thing on Linux: https://ghostty.org/docs/about#native). GTK is by various definitions the most popular, widespread GUI toolkit on Linux that makes your app fit into _most_ ecosystems. So, GTK it is.
I hope `libghostty` will give rise to other apprts (maintained by 3rd parties, it's hard enough for me to maintain macOS and GTK) so that you aren't forced into it. See https://ghostty.org/docs/about#libghostty For example Wraith is a Wayland-native Ghostty frontend (no GTK): https://github.com/gabydd/wraith Awesome.
account42 4 hours ago [-]
> GTK is by various definitions the most popular, widespread GUI toolkit on Linux that makes your app fit into _most_ ecosystems.
I disagree. Qt is also quite popular and much better at adapting to the environment it runs in.
maplant 21 minutes ago [-]
This is really just my opinion but I always can’t tell when an app uses QT and not positively. QT just looks uglier and feels more windows XP-esque than GTK apps
johnisgood 3 hours ago [-]
How about wxWidgets or Tcl/Tk or Fyne?
jamespo 1 hours ago [-]
This is where your fork can come in
Arrowmaster 10 hours ago [-]
You didn't cover it but is Ghostty still entirely dependent on libadwaita for most of its UI features? I completely lost interest when it was still in beta and I found out many features were disabled on Linux if you didn't want it to look and behave as a Gnome app.
mitchellh 9 hours ago [-]
Yes, its a hard dependency. But we go out of our way to add CSS classes to our UI widgets and even have a configuration in Ghostty to supply custom CSS directly (without you having to mess with gsettings or anything). We've seen some pretty incredible customizations in our showcase channel in Discord.
We haven't committed to our CSS classes yet as a stable API but we plan to do that in the next release cycle. Still, they haven't changed much in a year. :)
nothankyou777 59 minutes ago [-]
> CSS classes
GTK has gotten so fat that it's more like a 2nd-rate Electron. Not that Electron would have done Ghostty any good...
I have a bad feeling that the only decent & consistent UI option under Linux is to target Win32 API, then run it under Wine.
aidenn0 9 hours ago [-]
I hate GTK enough that I'm considering porting Ghostty to literally any other GUI system. I think that Qt is probably the only alternative that anyone might consider "platform native" so I'll probably go that direction, even though Qt development is rather special in its own way (you know how GTK decided C needed an object system? Qt decided that C++ needed a more better object system).
AceJohnny2 8 hours ago [-]
> Qt decided that C++ needed a more better object system
I haven't used Qt, nor C++, in many moons, but my understanding was that `moc` [1] filled a gap of run-time dynamicism that C++ didn't natively support when it was invented. Has C++ since evolved to make that obsolete? Seems like moc is still a thing.
I like Linux because it gives me the freedom to make my system behave how I want. The GNOME devs seem to think that GNOME should only behave how they want. For example, last time I checked, GNOME required a third-party plugin just to move the clock from the center of the status bar to the side.
I'm not at all surprised to see that this mindset extends to GTK.
dismalaf 11 hours ago [-]
Writing Gnome Shell extensions is easy, they're just JS scripts...
If you really need to move your clock with a bunch of clicks, there's also KDE which is less opinionated...
hactually 13 hours ago [-]
Can you do that on Windows/mac?
Gnome devs not withstanding, you have access to the source to change it if you want or put up a PR?
Lerc 12 hours ago [-]
Being able to make a small change is good when every thing is well defined small parts. You can change the part you want and then use everything else as per normal. If everything is so tightly integrated that you end up having to maintain a fork of a large project, it doesn't work out so well.
I don't know which is true for this particular case, but I'd hazard a guess that it is a much bigger task than it needs to be.
I have seen Gnome devs talk of removing features because people were using them the wrong way. Not that people weren't using the features at all, just not for the purpose for which they were written. Experiences like that make me think that pull requests wouldn't get you very far either.
eviks 8 hours ago [-]
You can't put up a PR if the gate keepers reject your whole design approach
cuu508 5 hours ago [-]
As a gatekeeper in an unrelated small project, I understand gatekeepers being selective. You have a vision, design standards, quality standards. Drive-by PRs that add "just this one thing I need" features is how your well-designed, cohesive project becomes a kitchen sink of shit.
eviks 5 hours ago [-]
> You have a vision, design standards, quality standards.
Unless, of course, all of those are shit, so a more design-competent person can drive by with an improvement, which will be rejected because it's too shiny
gf000 3 hours ago [-]
Well, yeah. They have their own design approach, if you don't take that into consideration, aren't you the one that in the wrong?
eviks 3 hours ago [-]
You're not, that depends entirely on the assessment of the relative approaches and whom you care more about, users or a subset of designers closest to the gates.
But that's beside the point, the point was the criticism of the "send a PR" even though that resolves nothing due to the mismatch.
Fnoord 5 hours ago [-]
2025, still cannot have taskbar on left or right side in Windows 11.
I can do that on GNOME and macOS. And yes, with 21:9 it is very nice. With a vertical monitor or a 3:2 (Surface), not so much.
ChocolateGod 4 hours ago [-]
You have to install an extension to do that on GNOME, likewise on Windows 11 you can use Explorer Patcher.
Both "monkey patch" the shell.
jcastro 13 hours ago [-]
> just to move the clock from the center of the status bar to the side.
And I like linux because there are plenty of people who also do not care about this and want to just use their computer.
const_cast 10 hours ago [-]
You can "just use" KDE too. The default are actually less insane than gnome, it's easier to use.
The idea that more functionality makes software less usable makes no sense to me. No, it's more usable.
Its like when people argue that iOS not allowing anything other than safari is a good thing.
Okay... how? Because if you like safari, nothing changes for you. You just keep using it. You wouldn't even be able to tell.
Similarly, if you like KDE you can just... use it. You don't actually have to change anything. There's no gun to your head. If you're the type of person who just takes software and uses it, then great - you don't need Gnome for that. KDE is actually better at that, IMO.
AndyKelley 13 hours ago [-]
Oh, I would love it if Wayland provided a standard UI toolkit (server-side)! Is that a thing that happened when I wasn't looking?
flohofwoe 4 hours ago [-]
I don't think we will even see universal support for server-side window decorations in our lifetime, so don't hold your breath ;)
(yes I'm aware of libdecor, but it sucks to have to pull in yet another complex dependency into clients)
account42 4 hours ago [-]
While pulling in a library just for window decorations is insane, the same could make sense for a full UI toolkit - after all, that's how standard UI components have worked on e.g. Windows. In a way, Qt can already fulfill that role because by default it tries to adapt to the look and feel of the platform it runs on, including using GTK themes. Too bad that it's a bloated pig without a stable ABI that would allow you to use the system version.
flohofwoe 3 hours ago [-]
> after all, that's how standard UI components have worked on e.g. Windows
Standard UI components on Windows are in user32.dll, and that's guaranteed to exist on each Windows installation all the way back to Windows NT.
And to just get an empty decorated window all I need to do is call CreateWindowEx() (which will always look consistent), all the rendering inside that window can then be done through one of the 3D APIs.
Same on macOS, I don't need any optional dependencies to create a decorated empty window which I can then render into with Metal.
For that same scenario (3D rendering into an empty window), Wayland only guarantees me a bare undecorated rectangle I can draw into with GL or Vulkan (and I wouldn't be surprised if even that is an optional feature I need to query first lol). And even if both GTK and Qt would be guaranteed to be installed on each Linux desktop system (so that I can pick one of two frameworks to give me a dedorated window, that would be overkill if I just want an empty window for 3D rendering - and even then I don't know if a window created through Qt would look consistent on a GNOME desktop or vice versa).
Of course that topic has been discussed to death without anybody who could fix that problem once and for all (by making the server-side decoration extension mandatory for desktop Linux systems) even recognizing that this is an issue that needs fixing.
Tbh, I don't even understand why desktop Linux needs more than a single Wayland implementation. So much wasted redundant work which could be put into actual improvements.
king_geedorah 13 hours ago [-]
No, there are no protocols intended to implement such a thing at this time. I'm not aware of anybody attempting to spec out such a protocol either, but I do think it's a really interesting idea.
Edit: s/protocol/interface
account42 4 hours ago [-]
There is about zero chance that Gnome would implement such a protocol which makes the whole endeavor pointless. They can't even agree on server side window decorations.
antihero 5 hours ago [-]
How would this work given that the major DE's have completely different UX and design?
AndyKelley 5 hours ago [-]
That's precisely the point! It would be really nice for applications to be able to operate agnostic from the DE's decisions about UX and design. Applications want something much more high level: button here, scroll bar there, text input here. It's the DE's job to make such things accessible and look pretty. If you think about it, that's precisely why the web is a popular user interface target: the application has a much higher level interface, and all those concerns are, correctly, handled at a different abstraction layer.
jon-wood 4 hours ago [-]
I don’t think it’s possible to build a generic UI across DEs, at least if you actually want them to feel native. They’ve all got different standards, so while Gnome might have a button here, a text box here, and scroll bar there on KDE a scroll bar here, text box here, and then the button might make more sense.
Cloudef 5 hours ago [-]
Server side ui toolkit doesnt make much sense to me. Better idea is to target some multimedia layer like web browser, electron, etc ... Or just hope someone someday comes up with UI library that doesnt suck.
cosmic_cheese 13 hours ago [-]
In my view the primary reason for GTK’s prominence on Linux rides on one thing primarily: it’s got C bindings, and thus it has decent bindings for just about every other language under the sun too. If you’re not trying for anything fancy, these bindings can even be auto-generated.
The runner up Qt is much more tightly tied to C++ and Python to its detriment. You really need to meet devs where they’re at instead of insisting that they adopt a particular language to use your UI toolkit.
Aside from that, at the end of the day, if you’re building a full fat complex desktop app an old style imperative UI toolkit is probably one of the more practical choices you can make. They have an exhaustive set of battle tested, accessible widgets built in and their pitfalls are well known. Newer approaches expect you to write or import everything and start requiring increased contortions from the developer past a certain point of complexity.
bobajeff 13 hours ago [-]
Actually the auto generated bindings can be attributed to the gobject system. It's a very interesting system, similar DCOM in Windows.
Too bad it's so poorly documented. It seems to me like advanced technology left over from a dead civilization, that's being handled by cave people.
Aren't GTK and Qt (community edition) both LGPL (though different versions)?
So Electron does not have downsides? Like far worse platform integration.
ozim 2 hours ago [-]
Well Qt license is not annoying.
Qt the company is annoying because they make it super hard to use community edition and it is super annoying having per developer licensing with all kinds of super annoying BS one have to deal with when developing for Qt.
For Electron I can get 20 devs hired tomorrow or I myself can start project right away and be up and running in minutes.
danieldk 48 minutes ago [-]
Yep, externalization of costs, make it easier for yourself and shittier for the user. Well done ;).
That said, Electron has made the number of Linux apps go up, which is a win. Still highly prefer native macOS apps on Mac and GTK/Qt apps on Linux, but I know that's a losing battle.
TheDong 8 hours ago [-]
> It is my choice not to use it and I am fine with that. However I also have encountered people who seem to think it is not my choice not to use it
I'm curious what the main opposing opinion you've hit there is?
Is it accessibility and non-roman-alphabet input? Those are the things that kinda stand out to me as "gtk does this pretty well, and most developers who hand-roll stuff wouldn't think about it".
carodgers 6 hours ago [-]
Fun fact. In Ghostty and (some) other GTK apps, if your mouse leaves the window, the first scroll click after re-entering the window is ignored. This is due to an ancient bug first identified in 2015.
There are no plans for a fix. The maintainer recommends waiting for Wayland.
jeroenhd 2 hours ago [-]
From what I can tell, that's an XInput2 bug, not a GTK bug. I suppose GTK can try to implement workarounds like the Chromium heuristic (https://issues.chromium.org/issues/41243294) but the problem lies upstream.
pilif 5 hours ago [-]
Reading the report you reference and other issues linked there, I would say that multiple attempts were made to fix it, all of which unfortunately required some heuristics and all of which have broken something else that was deemed worse.
It seems to boil down to an issue in the underlying X11 machinery and it would need to be fixed there first to build a basis on which proper fixes can be implemented.
Given that X11 is in maintenance mode (and as its fans keep saying: It works perfectly fine and doesn't need any more work done on it), it's not likely that's happening.
So, yes, given that information (and I just arrived at that bug report through your post), I would indeed say that waiting for Wayland is the only option they have. All other attempts ended up causing worse issues.
account42 4 hours ago [-]
Other toolkits don't seem to have this issue on X11.
So I guess the "fix" would be to have two completely separate input handlers on X11, one of which supporting smooth scrolling and multitouch, the other not and then offering users a toggle in the style of
[ ] do not ignore the first scroll input after focus loss, but disable smooth scrolling and multitouch
Plus handling all the potential issues by having two separate input handlers.
That's asking a bit much for this particular issue und greatly smells like a case of XKCD 1172
monksy 7 hours ago [-]
Biggest issue I have with Ghostty is that on the mac with Nano.. you can't copy and paste multiple lines into the editor. It's something about how the terminal handles "bracketed pasting".. but yet this isn't an issue with iterm2 and term.
dewey 6 hours ago [-]
I've used Ghostty as my default terminal since I set up my new computer a couple of months ago. The only issue I have is the missing search which I often reach for to look through output that I didn't pipe anywhere.
> Might be $TERM needs to be set or you need to add ghostty to terminfo
Yeah, except that the specific terminfo needed for ghostty isn't installed anywhere on the boxes you ssh into ... you need to manually install it on everysingle one of them.
That in and of itself makes it truly painful to switch to ghostty.
And there are still a lot of other issues, like e.g. building the tip is a freaking nightmare of dependencies and weird issues (hard reliance on specific versions of the zig compiler and of something called "blueprint compiler", etc...)
Not ready for prime time by a mile IMO.
biorach 2 hours ago [-]
> the specific terminfo needed for ghostty isn't installed anywhere on the boxes you ssh into ... you need to manually install it on every single one of them.
Yeah this is going to be an issue with any of the newer terminal emulators. No big deal. Updating terminfo is easy. If you can't then just set TERM=xterm
> Not ready for prime time by a mile IMO.
Nah, the issue is your lack of experience and understanding of the basics is terminals.
ur-whale 2 hours ago [-]
> Updating terminfo is easy.
lol.
sure, very easy to do this on order of magnitude 1000 remote machines whose various OS's are entirely managed by automation.
biorach 1 hours ago [-]
no need for the bitchy response.
paraboul 2 hours ago [-]
I'm not sure how the fact that it's complicated to compile makes it unready for prime time.
As for $TERM, you can simply default it to `xterm-256color` which is more than enough
ha1zum 6 hours ago [-]
This could be a valid bug that you can report
qweiopqweiop 6 hours ago [-]
No command f is the killer for me
throw10920 9 hours ago [-]
> also verifying with Valgrind every step of the way
This is...both extremely obvious, and also not something that I've ever done before, thought of doing, or seen anyone else do.
Every single instance of Valgrind usage I've encountered or initiated has been triggered by a specific bug or performance regression.
Proactive use of the Valgrind suite (Memcheck and Helgrind at least) as part of the development process would probably result in massively better stability of most tools - and would also make it far easier to find bugs (as you could find them when they were introduced rather than hundreds of commits later).
any1 18 minutes ago [-]
I've used valgrind proactively as long as I've been programming in C and C++.
The errors that are caught by valgrind (and asan) will very often not cause immediate crashes or any kind of obvious bugs. Instead, they cause intermittent bugs that are very hard to catch otherwise. They may even be security vulnerabilities.
Another good reason for using it proactively is that small memory leaks tend to sneak in over time. They might not cause any issues and most of them aren't accumulative. However, having all those leaks in there makes it much more difficult to find big leaks when they happen because you have to sift through all the insignificant ones before you can fix the one that's causing problems.
account42 3 hours ago [-]
I've used Valgrind (mainly memcheck) as a proactive tool or at least as a tool to fish for easy to fix issues before spending too much time debugging specific reports. Main issue is the huge performance overhead that make interactive use under it less than fun - but IMO running your testsuite under it from time to time at least is a no brainer.
ur-whale 2 hours ago [-]
> Proactive use of the Valgrind suite (Memcheck and Helgrind at least) as part of the development process
Yeah, except that it's: slow and expensive and therefore can't be a part of the "short cycle" (edit code, compile, test, iterate) only the "long cycle" (nightly build, test suite). Also valgrind is not exactly designed to directly integrate in a test suite and that requires work.
schmichael 14 hours ago [-]
I'm curious if Rust would have prevented the memory correctness errors assuming it replaced Zig in this scenario. It sounds like the vast majority were due to Zig/C interactions which makes me believe Rust would have had the same issues, but as a Go developer I am only guessing. I'm curious if there is a language that provides more tools to ensure correctness even when you're interacting with a huge amount of C.
ethan_smith 9 minutes ago [-]
Rust would face similar issues. Its safety guarantees only apply within Rust code; the FFI boundary with C/GObject is inherently unsafe and requires manual lifetime management. Rust's borrow checker can't verify external code's memory usage.
mitchellh 14 hours ago [-]
Hi @schmichael ;) Rust would've prevented one. The rest Rust wouldn't have prevented since as you already noticed, it was in the boundary layer and semantics of a C API. It would've only been as safe as the Rust wrapper. One argument is that the richer, more proven ecosystem of wrapper libraries may have prevented it versus my DIY wrappers.
The one Rust would've prevented was a simple undefined memory access: https://github.com/ghostty-org/ghostty/pull/7982 (At least, I'm pretty sure Rust would've caught this). In practice, it meant that we were copying garbage memory on the first rendered frame, but that memory wasn't used or sent anywhere so in practice it was mostly safe. Still, its not correct!
pornel 14 hours ago [-]
Rust has safe and reliable GTK bindings. They used gir to auto-generate the error-prone parts of the FFI based on schemas and introspection: https://gtk-rs.org/gir/book/
Rust's bindings fully embrace GTK's refcounting, so there's no mismatch in memory management.
mitchellh 14 hours ago [-]
We also use gir to auto-generate our bindings. But stuff like this is not represented in gir: https://github.com/ghostty-org/ghostty/commit/7548dcfe634cd9... It could EASILY be represented in a wrapper (e.g. with a Drop trait) but that implies a well-written wrapper, which is my argument. It's not inherent in the safety Rust gives you.
So the safety does rely on the human, not the machine.
pornel 10 hours ago [-]
This is a generic smart pointer. It had to be designed and verified manually, but that line of code has been written once 8 years ago, and nobody had to remember to write this FFI glue or even call this method since. It makes the public API automatically safe for all uses of all weak refs of all GTK types.
The Zig version seems to be a fix for one crash in a destructor of a particular window type. It doesn't look like a systemic solution preventing weak refs crashes in general.
ericbarrett 14 hours ago [-]
Do you mean gtk-rs (https://gtk-rs.org/)? I have done a bit of programming with it. I respect the work behind it, but it is a monumental PITA - truly a mismatch of philosophies and design - and I would a thousand times rather deal with C/C++ correctness demons than attempt it again, unless I had hard requirements for soundness. Even then, if you use gtk-rs you are pulling in 100+ crate dependencies and who knows what lurks in those?
pornel 9 hours ago [-]
Yeah, Rust isn't OOP, which is usually fine or even an advantage, but GUIs are one case where it hurts, and there isn't an obvious alternative.
> gtk-rs you are pulling in 100+ crate dependencies and who knows what lurks in those?
gtk-rs is a GNOME project. A lot of it is equivalent to .h files, but each file is counted as a separate crate. The level of trust or verification required isn't that different, especially if pulling a bunch of .so files from the same org is uncontroversial.
Cargo keeps eliciting reactions to big numbers of "dependencies", because it gives you itemized lists of everything being used, including build deps. You just don't see as much inner detail when you have equivalent libs pre-built and pre-installed.
Crates are not the same unit as a typical "dependency" in the C ecosystem. Many "dependencies" are split into multiple crates, even when it's one codebase in one repo maintained by one person. Crates are Rust's compilation unit, so kinda like .o files, but not quite comparable either.
A Cargo Workspace would be conceptually closer to a typical small C project/dependency, but Cargo doesn't support publishing Workspaces as a unit, so every subdirectory becomes a separate crate.
conradev 12 hours ago [-]
I remember it being bad enough for a project I was working on that the engineer working on it switched to relm: https://relm4.org
I'm sure the gtk-rs bindings are pretty good, but I do wonder if anyone ran Valgrind on them. When it comes to C interop, Rust feels weirdly less safe just because of the complexity.
schmichael 14 hours ago [-]
Hey Mitchell! Leave it to me to bait the comments. :)
Thanks for validating my assumption that once you introduce a big blob o' C all bets are off and you're back to Valgrind (or similar tooling).
> One argument is that the richer, more proven ecosystem of wrapper libraries may have prevented it
Yeah but where's the fun in that? ;)
ozgrakkurt 3 hours ago [-]
It is so much more difficult to write c bindings in rust.
Maybe they wouldn’t even be able to write gtk bindings in rust
steveklabnik 2 hours ago [-]
gtk bindings in Rust have existed for like, ten years.
14 hours ago [-]
WD-42 14 hours ago [-]
I think one of the main points of the article was about how shockingly few memory issues they have encountered. He talks about how great of a fit zig + valgrind is.
schmichael 14 hours ago [-]
Indeed, but I'm curious about the second class of memory correctness issue he mentions:
> 2. All other memory issues revolved around C API boundaries.
Is this something Rust, or any other language, has the ability to prevent any more than any other language? Or once you introduce a C API boundary is it back to tools like Valgrind?
NobodyNada 13 hours ago [-]
In general: whenever you call into C, you get all the safety of C, because C code can trivially have memory corruption bugs that corrupt memory "belonging" to Rust as well, inducing undefined behavior across your whole program [0].
In addition, it's often considered permissible for C APIs to exhibit undefined behavior if their API contracts are violated. This means that a bug in Rust code that calls into a C API incorrectly can (indirectly) cause undefined behavior. For this reason, all FFI calls are marked unsafe in Rust.
The typical approach to using C libraries from Rust is to create a "safe wrapper" around the unsafe FFI calls that uses Rust's type system and lifetimes to enforce the safety invariants. Of course it's possible to mess up this wrapper and have accidental undefined behavior, but you're much less likely to do so through a safe wrapper than if you use the unsafe FFI calls directly (or use C or Zig) for a couple reasons:
- Writing the safe wrapper forces you to sit down and think about safety invariants instead of glossing over it.
- Once you're done, the compiler will check the safety invariants for you every time you use the API -- no chance of making a mistake or forgetting to read a comment.
[0]: This could be avoided/mitigated with some kind of lightweight in-process sandboxing (e.g. Intel MPK + seccomp) to prevent C libraries from accessing memory that they don't own or performing syscalls they shouldn't. There's some academic research on this (and I experimented with it myself for a masters thesis project), but it generally requires some (minimal) performance overhead and code changes at language boundaries.
troad 10 hours ago [-]
> The typical approach to using C libraries from Rust is to create a "safe wrapper" around the unsafe FFI calls that uses Rust's type system and lifetimes to enforce the safety invariants.
Calling it a "safe" wrapper, when that safety is entirely dependent on (a) the correctness of the hand-written wrapper, (b) the safety of the underlying FFI code, has always been a huge stretch of terminology. It's more like a veil of safety, so we can shield our modest eyes from impure code that flaunts its unsafeness.
Rust has no magical ways of turning unsafe code safe, nor is it in any way special in being able to create statically-verifiable abstractions around an unsafe core.
Don't get me wrong, Rust is memory safe when used as a cohesive system, and I would encourage its use as such where memory safety is desired. But the idea of "safely" wrapping unsafe FFIs reminds me of the idea of packaging underwater mortgages into mortgage-backed securities and selling them as a safe investment.
gf000 1 hours ago [-]
But that wrapper clearly delineates two, previously mixed domain of bugs, reducing the complexity of understanding any "line".
It's much much easier to say that a reference is alive here, and only here can we derefence it, AND every other business code elsewhere.
NobodyNada 7 hours ago [-]
> Rust has no magical ways of turning unsafe code safe
Fully agreed on that -- the unsafe keyword means it's unsafe.
> nor is it in any way special in being able to create statically-verifiable abstractions around an unsafe core.
This isn't really true. Rust's type system has:
- Affine types
- Lifetimes
- Borrowed and exclusive references
- Thread-safety
- Explicit delineation between safe and unsafe code -- with no UB in safe code, and a (cultural) design principle that unsafe code is not allowed to make unchecked assumptions about the behavior of safe code
Most mainstream languages do not have any one of these features, let alone all of them. Thus, Rust's ability to "create statically-verifiable abstractions around an unsafe core" is in practice far more powerful than in C, C++, or Zig. You certainly have the ability to create some such abstractions in other languages, but you cannot statically verify nearly as many properties. (And of course there are languages like SPARK that can verify even more statically than Rust.)
In my experience, as a systems programmer who heavily uses Rust to interact with FFI, hardware MMIO and DMA, interrupt handling, networking code, etc., Rust's ability to safely abstract unsafe primitives is easily the most practically useful aspect of the language. It's not a silver bullet that turns incorrect code into correct code, but it is incredibly good at verifying the correctness of a large application built from small low-level primitives. If you're interfacing with buggy C code, Rust certainly isn't going to help you much -- but it does makes a huge difference in preventing "you're holding it wrong" bugs when interacting with a C API.
An unsafe block declares an axiom: you're asserting to the compiler that you've verified (statically with the type system or dynamically with runtime assertions) all preconditions necessary for some primitive to be sound (free of UB). The compiler can then use that axiom to prove the soundness of all code that interacts with that primitive. When I write a driver to perform a DMA transfer, I only have to think through all the concurrency, alignment, lifetime, moveability, caching, and cancellation requirements once, and the compiler will check them for me every time I (or anyone else) use that driver in an application.
wofo 13 hours ago [-]
Having worked on a few Rust projects that interface with C libraries, I think your last question is a good summary: once you introduce a C API boundary it's back to tools like Valgrind.
Maybe you could even say Zig is at an advantage there, because tools like Valgrind are considered part of the game, whereas in Rust they are way less commonly used (pure-Rust codebases don't need anything of the sort, unless you are using `unsafe`).
sbt567 13 hours ago [-]
I vaguely remember that there is a new language that promises "Safety across FFI boundary", but can't recall the name
Footnote7341 14 hours ago [-]
I managed to write a fairly large GTK application without the GTK type system encroaching on my code at all. It just meant hooking a bunch of lambdas in where they want you to be inheriting from and extending their own classes to allow all the parts to communicate together.
In the end it wasn't that messy, but probably confusing for anyone used to writing dogmatic GTK applications.
ripley12 13 hours ago [-]
> This has already led to more easily introducing GUI features like a new GTK titlebar tabs option
If it’s not maximized, the space isn’t wasted. The title in the response image looks incredibly crowded. May be ok if several buttons could be removed from the titlebar.
eviks 8 hours ago [-]
It's literally wasted because it's used for nothing useful. Also, you can have other apps that now can take up less area.
mixmastamyk 7 hours ago [-]
Titlebars are quite useful, I use them frequently to move, raise, lower, and maximize windows.
huimang 3 hours ago [-]
Many people use tiling window managers, so title bars become useless. The first thing I did in configuring ghostty was disabling window decoration for this reason.
eviks 7 hours ago [-]
Oh sure, but some people use more ergonomic ways to perform those actions, so to them the title bars would be a waste even if not maximized
8f2ab37a-ed6c 14 hours ago [-]
Been a happy Ghostty user for a couple of months, it's my daily driver now as far as macOS terminals go. Thanks for all the hard work Mitchell & team.
stephen 11 hours ago [-]
I've been using Ghostty, and other GPU-based apps like Alacritty / WezTerm / Zed, because they're ofc better/faster...
Ironically they've all made my DX worse, by highlighting how terrible the nvidia drivers actually worked on both my old Regolith i3wm/compositor-less or new sway/wayland setup.
Like it's ridiculously terrible.
I've tried every magical env flag that Claude can think of, and 4 of the various 550/560/575/580 driver versions--they all suck at screensharing, or resume from sleep, or just out-right buginess/crashes/segfaults in the nvidia drivers.
It must have always been this bad, but I just didn't notice, b/c I never actually used my GPU? lol
aidenn0 9 hours ago [-]
I had a similar experience with Wayland. If I turned compositing effects of in X11, everything worked fine on my two machines (one with a 1050Ti, the other with an AMD card old enough to need the "radeon" driver). Wayland would lag, or crash or just show garbled output.
jwar767 14 hours ago [-]
We had a similar experience to this at work. We wrote a google cloud service that interfaced with firestore using F# and found it painful because the firestore library is meant to be used with C#. It worked decently well but it was hard to write idiomatic F# without having a bunch of wrapping functions.
WhyNotHugo 2 hours ago [-]
I wouldn’t call GTK the “native” framework on Linux/Wayland or Linux/X11.
Native would be talking to the compositor directly.
GTK provides a cross-platform layer of abstractions over the compositor. That’s the opposite of native.
There’s countless bugs in the Linux port for applications (eg: Firefox) which can’t be fixed because of a he abstractions done by GTK.
lumpa 57 minutes ago [-]
Linux people get really worked up when I say "platform-native". There is no such thing on Linux, but reasonable people agree that something like a GTK app (or Qt) feels "native" on *most desktops* over other applications.
"native" here means using the same toolkit as the desktop environment.
corsica 15 hours ago [-]
I don't get the hype around this application. The only UI Ghostty has is tabs and the context menu, is it really worth the integration pain and now this rewrite?
Maybe they're planning for more, like those GUI configuration dialogs that iterm2 has?
Kitty uses OpenGL for everything and draws its own tabs, they're fully customizable and can be made to look however you want. By not wasting time on integrating with massive frameworks for drawing tabs, Kovid was able to quickly implement really useful things that Ghostty is sorely missing, like wrapping the output of the last command in a pager (run 'ps -auxf' and press Ctrl+Shift+G — this thing so useful it's hard to go without it now. It also works for remote shells across SSH sessions.)
mitchellh 14 hours ago [-]
> The only UI Ghostty has is tabs and the context menu
- Tabs
- Splits
- "this process has exited" banner
- Close confirmation dialogs
- Change title dialog
- Unsafe paste detection dialogs
- Context menus
- Animated bells (opt in)
- "Quake-style" dropdown terminals (cross platform but different mechanisms)
- Progress bars (ConEmu OSC 9;4)
- macOS: Apple Shortcuts Integration
- macOS: Spotlight Integration
Probably more I'm not thinking of. It's unfair to say it's just tabs. Could we have done this without a GUI toolkit? Of course! But the whole mission statement of this project was always to use platform-native (for various definitions) toolkits so that it _feels_ native.
That's not for everyone, and that's the great thing about the wonderful vibrant terminal ecosystem we have.
> is it really worth the integration pain and now this rewrite?
There's definitely a lot more on the way.
The first goal and primary focus of the project was to build a stable, feature rich (terminal sequences) terminal emulator. We're basically there. Next up, we're expanding GUI functionality significantly, including having more escape sequences result in more native GUI elements. But also traditional things like preferences GUIs, yes.
We're also integrating a lot more deeply with native features provided by each platform (somewhat related to the GUI toolkit choice), such as automatic iCloud syncing of your configuration on macOS. Now that the terminal is stable, we can start to really lean in to application features.
This isn't for everyone. Some people like Kitty's textual tabs. That's fine! It's a tradeoff. That's the beauty of choice. :) Kitty is a great terminal, if you prefer it, please use it. But it has completely different tradeoffs than Ghostty.
bpbp-mango 3 hours ago [-]
saved sessions in a tree style with folders would be a nice advanced feature!
LambdaComplex 13 hours ago [-]
I know I'm about to show my ignorance regarding GUI programming here, but: would SDL2 be a suitable choice? Or would that be too low-level? Or just...the wrong sort of library?
troad 9 hours ago [-]
SDL2 wouldn't be appropriate for what they're trying to do.
SDL2 is more of a drawing and graphics library. You tell it to put a triangle here, it puts a triangle there. But it has no idea what a button should look like - how it should behave, how it should be animated - on Mac, on Windows, on KDE, on Gnome, etc. You could try to painstakingly recreate this look and feel for each platform, but it's a lot of effort, you probably won't get it quite right, you'll make oversights on accessibility and internationalisation, and your hard work will instantly look dated once the platform evolves.
To make native GUIs, you need to talk to the libraries that draw platform-native components, like buttons, for you. But of course each platform works totally differently, and the whole affair is honestly kind of a mess, which is why truly native cross-platform applications tend to be fairly rare in practice. Maintaining five different GUI code bases for all sorts of fringe platforms is not, in most cases, a good use of time. For most apps, either you stick to native and cut less significant platforms, or you abandon native altogether and just use a cross-platform wrapper like Electron.
bitwize 5 hours ago [-]
Unless you plan on writing your entire UI from scratch, like, from the framebuffer on up (in which case it will integrate poorly with the rest of the desktop) you must use one of the common widget toolkits: GTK or Qt. If you want the flexibility of not having to commit to C++, GTK is your only choice.
sevg 7 hours ago [-]
> Kovid was able to quickly implement
Is this new account actually Kovid?
Context: “aumerle” had posted only about Kitty for years as though impartial. And talked about Kovid as if they were a different person. Turns out “aumerle” is Kovid and got banned. He was trash-talking ghostty and advertising Kitty in every ghostty thread. (He does the same using “aumerlex” on reddit, but nobody has called him out on there yet.)
I’m suspicious here because Kovid spent hours trying to force me to admit that he writes code faster than Mitchell XD https://news.ycombinator.com/item?id=42567224 (you’ll need “showdead” enabled, all of Kovid’s comments got flagged to death).
alberth 14 hours ago [-]
In addition to what others have said (positively), ‘libghostty’ is also a game changer.
It’s like the “WebKit” for terminal, as I understand it.
Anyone could drop-in libghostty, and immediately have a fully functional terminal.
Lerc 14 hours ago [-]
I went on a big meandering hunt for a terminal application that did what I wanted. I have tried many and while nothing perfectly met my needs, Ghostty is the one I am using now.
That counts for something.
Perhaps it is just it lacks an obvious reason to move away from it. Usually, the thing that made me try another terminal was because of something I couldn't do. It wasn't a matter of listing all the pros and cons and going with the best one. It has just found a home with me because it hasn't outstayed its welcome.
do_not_redeem 14 hours ago [-]
Well... a terminal is a GUI app, so they had to choose some GUI framework. On Linux GTK is as good a choice as any. (Yes I know you can skip the framework and talk to X11/Wayland directly, like xterm/foot do, but that's a pain all of its own.)
akulbe 13 hours ago [-]
What about Qt? Would that have been a better experience? Or would you experience different issues?
hyperbolablabla 14 hours ago [-]
Agreed, seems like a lot of unnecessary girating just to implement something that would've been much simpler + cross-platform with a custom UI toolkit and something like opengl. Tabs are like UI 101
ChocolateGod 14 hours ago [-]
Easier integration with the desktops accessibility and input stack? When using GTK, you would probably also get out the box better performance/power on Wayland since it can take care of partial surface updates etc for you.
WD-42 14 hours ago [-]
Luckily the UI and the core (libghostty) are separate so you can girate out your own UI 101 version without GTK if you'd like.
I'll take QObject over GObject any day of the week.
WD-42 14 hours ago [-]
Very nice writeup! I was actually just wondering what was going on with Ghostty, I've been daily driving it since initial release but I haven't noticed any updates since then (not that anything is particularly lacking, it's a great terminal!)
Good to hear the Mitchell and the team are still hacking away at it! Thanks for the great software!
mitchellh 14 hours ago [-]
Hold onto your butts cause 1.2 is weeks away and the release notes if printed would cause a [larger than we already have] deforestation problem.
WD-42 13 hours ago [-]
Looking forward to it!
Cloudef 5 hours ago [-]
Honestly i'd write the UI parts in vala if i'd want to make a gnome native app
rweichler 7 hours ago [-]
> This is now my 5th time writing the GUI part of Ghostty from scratch: [...] once on macOS with SwiftUI, then on macOS with AppKit plus SwiftUI [...]
Ha, that's a nice way of wording that. I'd take it a step or two further. :)
metaltyphoon 13 hours ago [-]
“Ghostty is cross platform…” but not on windows :D
“App XYZ is mobile ready…” but not on Android.
Same vibe
AndyKelley 12 hours ago [-]
Windows is becoming less and less of a platform every year
metaltyphoon 12 hours ago [-]
Not saying you are wrong, but this is akin to “this is the year of the Linux Desktop”.
You probably don’t have this telemetry but have you thought about how having window support helps Zig adoption?
Anecdotal, at day job, we started to use Zig build system to target Windows because that’s where the customers are.
AndyKelley 10 hours ago [-]
Yeah. I just wish Microsoft were better stewards of the OS.
metaltyphoon 1 hours ago [-]
100% agreed
epolanski 4 hours ago [-]
Missing windows still means missing most computer users and developers specifically.
sevensor 10 hours ago [-]
Is that the OS from the people who make Excel?
bitwize 5 hours ago [-]
I remember the days when "cross-platform" meant it worked on both operating systems: Windows 95 and Windows NT!
keithnz 12 hours ago [-]
WezTerm is a great terminal that IS cross platform and works well on windows (and arguably better than ghostty)
metaltyphoon 11 hours ago [-]
Yep. I've migrate to it as I need a terminal that is truly cross platform.
Zambyte 11 hours ago [-]
Cross platform doesn't mean your platforms. I use Ghostty on GNU/Linux and MacOS, because it truly is cross platform.
eviks 7 hours ago [-]
It doesn't mean his platforms, it means the top ones, so at least his and hundreds of millions of others'
mariusor 1 hours ago [-]
Terminals are not really targeting that entire demographic, and for the one they serve probably Mac/Linux form a majority vs Windows.
WhereIsTheTruth 7 hours ago [-]
Windows is just a web browser, yes i'm serious
bitwize 5 hours ago [-]
Windows is BonziBuddy with OS functionality attached.
working on this problem produced this library, which I am not proud of: https://github.com/gdzig/oopz
here's a snippet that kind of demonstrates the state of the API at the moment: https://github.com/gdzig/gdzig/blob/master/example/src/Signa...
also.. now I want to attempt to write a Ghostty frontend as a Godot extension
For example this is something you can do with typescript.
the Arguments { a: 1, b: 1, c: 1 } is not representable.This is why a surprising number of GTK applications (more than I realized) are coded in Vala. I lowkey wish they had just adopted D instead of building up Vala. D is basically compiled C# to me in its own ways.
Being pragmatic about the design of an ecosystem and working with it, could be seen as good programming vs the alternative of fighting that ecosystem and thus creating entirely new classes of bugs.
And this was what the GP was responding to. They were was that the pragmatism of working with that ecosystem showed good judgement.
In the past this has also been my assessment of GTK. It lead me to decide to take the other path, to never directly use GTK. I appreciate the value in having a unified user interface between applications, but I have always thought the features that GTK provides were not worth the penalties paid. I have worked around the edges of GTK in open source apps that are GTK based. That lead me to think that GTK and the GObject system is opinionated in a way that are not terribly compatible with my own opinions.
I don't hate that GTK exists, It is my choice not to use it and I am fine with that. However I also have encountered people who seem to think it is not my choice not to use it. There are a million and one other GUI toolkits out there, of which GTK is one of the most polished. I can't shake the feeling that if GTK were less dominant, some of the resources that go to polishing GTK might have been spent polishing a different framework with a nicer underlying architecture.
Of course what I consider nicer might not be what others consider nicer. Of those who use GTK, how many use it begrudgingly, and how many feel like it is the best tool for the job?
This might be amusing for me to say but... I also feel this way. I disagree a lot with the Gnome ecosystem's point of view. Funny!
Using GTK for Linux was a pragmatic choice. A goal of Ghostty is to be "platform-native" (defined here because there's no such thing on Linux: https://ghostty.org/docs/about#native). GTK is by various definitions the most popular, widespread GUI toolkit on Linux that makes your app fit into _most_ ecosystems. So, GTK it is.
I hope `libghostty` will give rise to other apprts (maintained by 3rd parties, it's hard enough for me to maintain macOS and GTK) so that you aren't forced into it. See https://ghostty.org/docs/about#libghostty For example Wraith is a Wayland-native Ghostty frontend (no GTK): https://github.com/gabydd/wraith Awesome.
I disagree. Qt is also quite popular and much better at adapting to the environment it runs in.
We haven't committed to our CSS classes yet as a stable API but we plan to do that in the next release cycle. Still, they haven't changed much in a year. :)
GTK has gotten so fat that it's more like a 2nd-rate Electron. Not that Electron would have done Ghostty any good...
I have a bad feeling that the only decent & consistent UI option under Linux is to target Win32 API, then run it under Wine.
I haven't used Qt, nor C++, in many moons, but my understanding was that `moc` [1] filled a gap of run-time dynamicism that C++ didn't natively support when it was invented. Has C++ since evolved to make that obsolete? Seems like moc is still a thing.
[1] https://doc.qt.io/qt-6/moc.html
I'm not at all surprised to see that this mindset extends to GTK.
If you really need to move your clock with a bunch of clicks, there's also KDE which is less opinionated...
Gnome devs not withstanding, you have access to the source to change it if you want or put up a PR?
I don't know which is true for this particular case, but I'd hazard a guess that it is a much bigger task than it needs to be.
I have seen Gnome devs talk of removing features because people were using them the wrong way. Not that people weren't using the features at all, just not for the purpose for which they were written. Experiences like that make me think that pull requests wouldn't get you very far either.
Unless, of course, all of those are shit, so a more design-competent person can drive by with an improvement, which will be rejected because it's too shiny
But that's beside the point, the point was the criticism of the "send a PR" even though that resolves nothing due to the mismatch.
I can do that on GNOME and macOS. And yes, with 21:9 it is very nice. With a vertical monitor or a 3:2 (Surface), not so much.
Both "monkey patch" the shell.
And I like linux because there are plenty of people who also do not care about this and want to just use their computer.
The idea that more functionality makes software less usable makes no sense to me. No, it's more usable.
Its like when people argue that iOS not allowing anything other than safari is a good thing.
Okay... how? Because if you like safari, nothing changes for you. You just keep using it. You wouldn't even be able to tell.
Similarly, if you like KDE you can just... use it. You don't actually have to change anything. There's no gun to your head. If you're the type of person who just takes software and uses it, then great - you don't need Gnome for that. KDE is actually better at that, IMO.
(yes I'm aware of libdecor, but it sucks to have to pull in yet another complex dependency into clients)
Standard UI components on Windows are in user32.dll, and that's guaranteed to exist on each Windows installation all the way back to Windows NT.
And to just get an empty decorated window all I need to do is call CreateWindowEx() (which will always look consistent), all the rendering inside that window can then be done through one of the 3D APIs.
Same on macOS, I don't need any optional dependencies to create a decorated empty window which I can then render into with Metal.
For that same scenario (3D rendering into an empty window), Wayland only guarantees me a bare undecorated rectangle I can draw into with GL or Vulkan (and I wouldn't be surprised if even that is an optional feature I need to query first lol). And even if both GTK and Qt would be guaranteed to be installed on each Linux desktop system (so that I can pick one of two frameworks to give me a dedorated window, that would be overkill if I just want an empty window for 3D rendering - and even then I don't know if a window created through Qt would look consistent on a GNOME desktop or vice versa).
Of course that topic has been discussed to death without anybody who could fix that problem once and for all (by making the server-side decoration extension mandatory for desktop Linux systems) even recognizing that this is an issue that needs fixing.
Tbh, I don't even understand why desktop Linux needs more than a single Wayland implementation. So much wasted redundant work which could be put into actual improvements.
Edit: s/protocol/interface
The runner up Qt is much more tightly tied to C++ and Python to its detriment. You really need to meet devs where they’re at instead of insisting that they adopt a particular language to use your UI toolkit.
Aside from that, at the end of the day, if you’re building a full fat complex desktop app an old style imperative UI toolkit is probably one of the more practical choices you can make. They have an exhaustive set of battle tested, accessible widgets built in and their pitfalls are well known. Newer approaches expect you to write or import everything and start requiring increased contortions from the developer past a certain point of complexity.
Too bad it's so poorly documented. It seems to me like advanced technology left over from a dead civilization, that's being handled by cave people.
So we are left with Electron…
So Electron does not have downsides? Like far worse platform integration.
Qt the company is annoying because they make it super hard to use community edition and it is super annoying having per developer licensing with all kinds of super annoying BS one have to deal with when developing for Qt.
For Electron I can get 20 devs hired tomorrow or I myself can start project right away and be up and running in minutes.
That said, Electron has made the number of Linux apps go up, which is a win. Still highly prefer native macOS apps on Mac and GTK/Qt apps on Linux, but I know that's a losing battle.
I'm curious what the main opposing opinion you've hit there is? Is it accessibility and non-roman-alphabet input? Those are the things that kinda stand out to me as "gtk does this pretty well, and most developers who hand-roll stuff wouldn't think about it".
https://bugzilla.gnome.org/show_bug.cgi?id=750994
There are no plans for a fix. The maintainer recommends waiting for Wayland.
It seems to boil down to an issue in the underlying X11 machinery and it would need to be fixed there first to build a basis on which proper fixes can be implemented.
Given that X11 is in maintenance mode (and as its fans keep saying: It works perfectly fine and doesn't need any more work done on it), it's not likely that's happening.
So, yes, given that information (and I just arrived at that bug report through your post), I would indeed say that waiting for Wayland is the only option they have. All other attempts ended up causing worse issues.
The issue comes from XInput2 (https://www.x.org/releases/X11R7.7/doc/inputproto/XI2proto.t...)
So I guess the "fix" would be to have two completely separate input handlers on X11, one of which supporting smooth scrolling and multitouch, the other not and then offering users a toggle in the style of
[ ] do not ignore the first scroll input after focus loss, but disable smooth scrolling and multitouch
Plus handling all the potential issues by having two separate input handlers.
That's asking a bit much for this particular issue und greatly smells like a case of XKCD 1172
Bit it's also the most mentioned issue: https://github.com/ghostty-org/ghostty/issues/189
Yeah, except that the specific terminfo needed for ghostty isn't installed anywhere on the boxes you ssh into ... you need to manually install it on every single one of them.
That in and of itself makes it truly painful to switch to ghostty.
And there are still a lot of other issues, like e.g. building the tip is a freaking nightmare of dependencies and weird issues (hard reliance on specific versions of the zig compiler and of something called "blueprint compiler", etc...)
Not ready for prime time by a mile IMO.
Yeah this is going to be an issue with any of the newer terminal emulators. No big deal. Updating terminfo is easy. If you can't then just set TERM=xterm
> Not ready for prime time by a mile IMO.
Nah, the issue is your lack of experience and understanding of the basics is terminals.
lol.
sure, very easy to do this on order of magnitude 1000 remote machines whose various OS's are entirely managed by automation.
As for $TERM, you can simply default it to `xterm-256color` which is more than enough
This is...both extremely obvious, and also not something that I've ever done before, thought of doing, or seen anyone else do.
Every single instance of Valgrind usage I've encountered or initiated has been triggered by a specific bug or performance regression.
Proactive use of the Valgrind suite (Memcheck and Helgrind at least) as part of the development process would probably result in massively better stability of most tools - and would also make it far easier to find bugs (as you could find them when they were introduced rather than hundreds of commits later).
The errors that are caught by valgrind (and asan) will very often not cause immediate crashes or any kind of obvious bugs. Instead, they cause intermittent bugs that are very hard to catch otherwise. They may even be security vulnerabilities.
Another good reason for using it proactively is that small memory leaks tend to sneak in over time. They might not cause any issues and most of them aren't accumulative. However, having all those leaks in there makes it much more difficult to find big leaks when they happen because you have to sift through all the insignificant ones before you can fix the one that's causing problems.
Yeah, except that it's: slow and expensive and therefore can't be a part of the "short cycle" (edit code, compile, test, iterate) only the "long cycle" (nightly build, test suite). Also valgrind is not exactly designed to directly integrate in a test suite and that requires work.
The one Rust would've prevented was a simple undefined memory access: https://github.com/ghostty-org/ghostty/pull/7982 (At least, I'm pretty sure Rust would've caught this). In practice, it meant that we were copying garbage memory on the first rendered frame, but that memory wasn't used or sent anywhere so in practice it was mostly safe. Still, its not correct!
Rust's bindings fully embrace GTK's refcounting, so there's no mismatch in memory management.
EDIT:
I looked it up because I was curious, and a Drop trait is exactly what they do: https://github.com/gtk-rs/gtk-rs-core/blob/b7559d3026ce06838... and as far as I can tell this is manually written, not automatically generated from gir.
So the safety does rely on the human, not the machine.
The Zig version seems to be a fix for one crash in a destructor of a particular window type. It doesn't look like a systemic solution preventing weak refs crashes in general.
> gtk-rs you are pulling in 100+ crate dependencies and who knows what lurks in those?
gtk-rs is a GNOME project. A lot of it is equivalent to .h files, but each file is counted as a separate crate. The level of trust or verification required isn't that different, especially if pulling a bunch of .so files from the same org is uncontroversial.
Cargo keeps eliciting reactions to big numbers of "dependencies", because it gives you itemized lists of everything being used, including build deps. You just don't see as much inner detail when you have equivalent libs pre-built and pre-installed.
Crates are not the same unit as a typical "dependency" in the C ecosystem. Many "dependencies" are split into multiple crates, even when it's one codebase in one repo maintained by one person. Crates are Rust's compilation unit, so kinda like .o files, but not quite comparable either.
A Cargo Workspace would be conceptually closer to a typical small C project/dependency, but Cargo doesn't support publishing Workspaces as a unit, so every subdirectory becomes a separate crate.
It is built on top of gtk4-rs, and fairly usable: https://github.com/hackclub/burrow/blob/main/burrow-gtk/src/...
I'm sure the gtk-rs bindings are pretty good, but I do wonder if anyone ran Valgrind on them. When it comes to C interop, Rust feels weirdly less safe just because of the complexity.
Thanks for validating my assumption that once you introduce a big blob o' C all bets are off and you're back to Valgrind (or similar tooling).
> One argument is that the richer, more proven ecosystem of wrapper libraries may have prevented it
Yeah but where's the fun in that? ;)
Maybe they wouldn’t even be able to write gtk bindings in rust
> 2. All other memory issues revolved around C API boundaries.
Is this something Rust, or any other language, has the ability to prevent any more than any other language? Or once you introduce a C API boundary is it back to tools like Valgrind?
In addition, it's often considered permissible for C APIs to exhibit undefined behavior if their API contracts are violated. This means that a bug in Rust code that calls into a C API incorrectly can (indirectly) cause undefined behavior. For this reason, all FFI calls are marked unsafe in Rust.
The typical approach to using C libraries from Rust is to create a "safe wrapper" around the unsafe FFI calls that uses Rust's type system and lifetimes to enforce the safety invariants. Of course it's possible to mess up this wrapper and have accidental undefined behavior, but you're much less likely to do so through a safe wrapper than if you use the unsafe FFI calls directly (or use C or Zig) for a couple reasons:
- Writing the safe wrapper forces you to sit down and think about safety invariants instead of glossing over it.
- Once you're done, the compiler will check the safety invariants for you every time you use the API -- no chance of making a mistake or forgetting to read a comment.
[0]: This could be avoided/mitigated with some kind of lightweight in-process sandboxing (e.g. Intel MPK + seccomp) to prevent C libraries from accessing memory that they don't own or performing syscalls they shouldn't. There's some academic research on this (and I experimented with it myself for a masters thesis project), but it generally requires some (minimal) performance overhead and code changes at language boundaries.
Calling it a "safe" wrapper, when that safety is entirely dependent on (a) the correctness of the hand-written wrapper, (b) the safety of the underlying FFI code, has always been a huge stretch of terminology. It's more like a veil of safety, so we can shield our modest eyes from impure code that flaunts its unsafeness.
Rust has no magical ways of turning unsafe code safe, nor is it in any way special in being able to create statically-verifiable abstractions around an unsafe core.
Don't get me wrong, Rust is memory safe when used as a cohesive system, and I would encourage its use as such where memory safety is desired. But the idea of "safely" wrapping unsafe FFIs reminds me of the idea of packaging underwater mortgages into mortgage-backed securities and selling them as a safe investment.
It's much much easier to say that a reference is alive here, and only here can we derefence it, AND every other business code elsewhere.
Fully agreed on that -- the unsafe keyword means it's unsafe.
> nor is it in any way special in being able to create statically-verifiable abstractions around an unsafe core.
This isn't really true. Rust's type system has:
- Affine types
- Lifetimes
- Borrowed and exclusive references
- Thread-safety
- Explicit delineation between safe and unsafe code -- with no UB in safe code, and a (cultural) design principle that unsafe code is not allowed to make unchecked assumptions about the behavior of safe code
Most mainstream languages do not have any one of these features, let alone all of them. Thus, Rust's ability to "create statically-verifiable abstractions around an unsafe core" is in practice far more powerful than in C, C++, or Zig. You certainly have the ability to create some such abstractions in other languages, but you cannot statically verify nearly as many properties. (And of course there are languages like SPARK that can verify even more statically than Rust.)
In my experience, as a systems programmer who heavily uses Rust to interact with FFI, hardware MMIO and DMA, interrupt handling, networking code, etc., Rust's ability to safely abstract unsafe primitives is easily the most practically useful aspect of the language. It's not a silver bullet that turns incorrect code into correct code, but it is incredibly good at verifying the correctness of a large application built from small low-level primitives. If you're interfacing with buggy C code, Rust certainly isn't going to help you much -- but it does makes a huge difference in preventing "you're holding it wrong" bugs when interacting with a C API.
An unsafe block declares an axiom: you're asserting to the compiler that you've verified (statically with the type system or dynamically with runtime assertions) all preconditions necessary for some primitive to be sound (free of UB). The compiler can then use that axiom to prove the soundness of all code that interacts with that primitive. When I write a driver to perform a DMA transfer, I only have to think through all the concurrency, alignment, lifetime, moveability, caching, and cancellation requirements once, and the compiler will check them for me every time I (or anyone else) use that driver in an application.
Maybe you could even say Zig is at an advantage there, because tools like Valgrind are considered part of the game, whereas in Rust they are way less commonly used (pure-Rust codebases don't need anything of the sort, unless you are using `unsafe`).
In the end it wasn't that messy, but probably confusing for anyone used to writing dogmatic GTK applications.
Yes! This is huge, I previously gave up on Ghostty because the title bar wasted so much space on my laptop screen: https://bsky.app/profile/reillywood.bsky.social/post/3lebapf...
I found the PR in case anyone else is curious what the new functionality looks like: https://github.com/ghostty-org/ghostty/pull/8166
Ironically they've all made my DX worse, by highlighting how terrible the nvidia drivers actually worked on both my old Regolith i3wm/compositor-less or new sway/wayland setup.
Like it's ridiculously terrible.
I've tried every magical env flag that Claude can think of, and 4 of the various 550/560/575/580 driver versions--they all suck at screensharing, or resume from sleep, or just out-right buginess/crashes/segfaults in the nvidia drivers.
It must have always been this bad, but I just didn't notice, b/c I never actually used my GPU? lol
Native would be talking to the compositor directly.
GTK provides a cross-platform layer of abstractions over the compositor. That’s the opposite of native.
There’s countless bugs in the Linux port for applications (eg: Firefox) which can’t be fixed because of a he abstractions done by GTK.
Maybe they're planning for more, like those GUI configuration dialogs that iterm2 has?
Kitty uses OpenGL for everything and draws its own tabs, they're fully customizable and can be made to look however you want. By not wasting time on integrating with massive frameworks for drawing tabs, Kovid was able to quickly implement really useful things that Ghostty is sorely missing, like wrapping the output of the last command in a pager (run 'ps -auxf' and press Ctrl+Shift+G — this thing so useful it's hard to go without it now. It also works for remote shells across SSH sessions.)
- Tabs
- Splits
- "this process has exited" banner
- Close confirmation dialogs
- Change title dialog
- Unsafe paste detection dialogs
- Context menus
- Animated bells (opt in)
- "Quake-style" dropdown terminals (cross platform but different mechanisms)
- Progress bars (ConEmu OSC 9;4)
- macOS: Apple Shortcuts Integration
- macOS: Spotlight Integration
Probably more I'm not thinking of. It's unfair to say it's just tabs. Could we have done this without a GUI toolkit? Of course! But the whole mission statement of this project was always to use platform-native (for various definitions) toolkits so that it _feels_ native.
That's not for everyone, and that's the great thing about the wonderful vibrant terminal ecosystem we have.
> is it really worth the integration pain and now this rewrite?
There's definitely a lot more on the way.
The first goal and primary focus of the project was to build a stable, feature rich (terminal sequences) terminal emulator. We're basically there. Next up, we're expanding GUI functionality significantly, including having more escape sequences result in more native GUI elements. But also traditional things like preferences GUIs, yes.
We're also integrating a lot more deeply with native features provided by each platform (somewhat related to the GUI toolkit choice), such as automatic iCloud syncing of your configuration on macOS. Now that the terminal is stable, we can start to really lean in to application features.
This isn't for everyone. Some people like Kitty's textual tabs. That's fine! It's a tradeoff. That's the beauty of choice. :) Kitty is a great terminal, if you prefer it, please use it. But it has completely different tradeoffs than Ghostty.
SDL2 is more of a drawing and graphics library. You tell it to put a triangle here, it puts a triangle there. But it has no idea what a button should look like - how it should behave, how it should be animated - on Mac, on Windows, on KDE, on Gnome, etc. You could try to painstakingly recreate this look and feel for each platform, but it's a lot of effort, you probably won't get it quite right, you'll make oversights on accessibility and internationalisation, and your hard work will instantly look dated once the platform evolves.
To make native GUIs, you need to talk to the libraries that draw platform-native components, like buttons, for you. But of course each platform works totally differently, and the whole affair is honestly kind of a mess, which is why truly native cross-platform applications tend to be fairly rare in practice. Maintaining five different GUI code bases for all sorts of fringe platforms is not, in most cases, a good use of time. For most apps, either you stick to native and cut less significant platforms, or you abandon native altogether and just use a cross-platform wrapper like Electron.
Is this new account actually Kovid?
Context: “aumerle” had posted only about Kitty for years as though impartial. And talked about Kovid as if they were a different person. Turns out “aumerle” is Kovid and got banned. He was trash-talking ghostty and advertising Kitty in every ghostty thread. (He does the same using “aumerlex” on reddit, but nobody has called him out on there yet.)
I’m suspicious here because Kovid spent hours trying to force me to admit that he writes code faster than Mitchell XD https://news.ycombinator.com/item?id=42567224 (you’ll need “showdead” enabled, all of Kovid’s comments got flagged to death).
It’s like the “WebKit” for terminal, as I understand it.
Anyone could drop-in libghostty, and immediately have a fully functional terminal.
That counts for something.
Perhaps it is just it lacks an obvious reason to move away from it. Usually, the thing that made me try another terminal was because of something I couldn't do. It wasn't a matter of listing all the pros and cons and going with the best one. It has just found a home with me because it hasn't outstayed its welcome.
Good to hear the Mitchell and the team are still hacking away at it! Thanks for the great software!
Ha, that's a nice way of wording that. I'd take it a step or two further. :)
“App XYZ is mobile ready…” but not on Android.
Same vibe
You probably don’t have this telemetry but have you thought about how having window support helps Zig adoption?
Anecdotal, at day job, we started to use Zig build system to target Windows because that’s where the customers are.