HACKER Q&A
📣 scott01

I'd like to practice coding GUI from scratch. Any recommendations?


Hi folks!

As the title says, I want to practice coding a GUI framework, probably in C++.

I read about a retained and an immediate modes, have a rough understanding how event loop works, and overall my goal is to practice architecture and optimization (especially cache-friendliness), and less so graphics and typography rendering, though I understand it's unavoidable to implement a rendering pipeline (I plan to start off with AGG or Skia graphics libraries).

The dummy app itself will be less about forms but more about data representation, e.g. an audio editor or a node-based system, where data should be updated and visualized in real time, and everything should feel responsive.

Could you please give some research directions? Maybe case studies, best practices, some interesting software, maybe to read more in detail about related architectures, etc.? Or maybe personal stories? I'm struggling to find related info which would not be focused on some framework, etc.


  👤 jasonhong Accepted Answer ✓
I'd recommend two things. The first is Brad Myers' Software Structures for User Interfaces course at Carnegie Mellon University, which focuses on the guts of how graphical user interfaces work.

https://www.cs.cmu.edu/~bam/uicourse/05631fall2021/

The second is Dan Olsen's book Developing User Interfaces, which has all of the details of how GUIs work, from graphics to interactor trees to events to dispatching. For some reason, it's absurdly expensive on Amazon right now.

Both Dan Olsen and Brad Myers were early pioneers in GUIs and GUI tools, so you'd be learning from the masters.


👤 cracrecry
I have done lots of UI interfaces in different platforms. I have used Motif and X Windows, Win32, MFC, Gtk, Qt, Cocoa, simple Web interfaces, DirectX, OpenGL, Metal.

I love Dear Imgui: https://github.com/ocornut/imgui

It is the simplest thing in the world. If you are starting and are going to do 3D graphics anyway you don't need state(you just redraw the screen 60 times per second).

Anything else is extremely sophisticated. I also loved Qt, but the policies got a little cumbersome, and went native.

The big problem is that with state there is a lot of complexity involved that is dependent on a platform, and once you pick one it is hard to change.

The big advantage of 3d graphics and dear imgui or any other open source software is that it works anywhere and you are not as dependent on a single company.


👤 TheTon
A lot of folks have given you the advice to learn one or more existing frameworks (Dear ImGui, Qt, Cocoa, etc). This is good advice, but I don't think anyone has yet articulated why it's good advice. I'll try ...

Good UI frameworks are composable, and progressively expose their API users (developers) to their constituent parts, which can include systems such as drawing/rendering, animation, compositing, event handling, text editing, view hierarchy, navigation, accessibility, and so forth. As you build more complex applications with a UI framework, you naturally find yourself customizing default behaviors or implementing new controls or functionality on top of the existing capabilities. You start to see how the framework itself is built just by using it.

Once you reach expert level with a UI framework, you will have a conceptual understanding of how high level features of the framework are implemented in terms of the lower level functionality. As an expert, you will feel confident that you could implement a new type of control, or reimplement existing functionality such that your version is a perfect peer to the built-in functionality from the library author on all important axes (developer API, performance, user experience, etc). In some cases this might be a lot of work, but at least you should know generally how to go about it if you had to.

See if you can get to expert level with at least 2 different styles of UI frameworks. At that point, you will be capable of building your own.


👤 smoyer
If you want to start from scratch, I'd recommend coding along with Casey on https://handmadehero.org. He develops an entire game starting with double-buffered pixel graphics and then moves on to sprite s with movement functions. The should give you plenty of background to be able to show a sound waveform (I'll offer one warning though ... Being able to edit sound I'm a way that still sounds good is much harder).

👤 gwmnxnp_516a
The problem of creating GUIs libraries almost from scratch is the platform fragmentation, which means that a cross-platform GUI libraries would have to abstract away the Windows API win32, that is one of the most stable and most complete GUI libraries; MacOSX Objective-C Cocoa; Unix and Linux X11 - X Windows System, that lacks Win32 button and other higher level widgets, in this case it is better to use GTK as backend instead of targeting X11 directly that may even be replaced with Wayland on major Linux distribtions; Linux Wayland backend directly; Linux framebuffer for embedded Linux systems; or OpenGL for a immediate mode GUI like Imgui. Another trouble is that GTK is not so stable like Win32 and has many breaking changes on every release that may require anything depending on this library to be modified.

The following design patterns are widely used with graphical user interfaces: observer-design pattern; model-view-controller; model-view-presentation; two-way-data binding; property binding; command design pattern; and composite design patterns for representing a collection of objects as single object.

For understanding event loop it may be much easier to implement a Xterm or VT100 keyboard-driven terminal user interface TUI since this does not requiring dealing with too many backends.


👤 thamer
I've written a fair share of GUI apps in C++ on multiple platforms, starting with Win32 API and MFC on Windows and later Qt on Linux. The way you write applications with these frameworks is different enough to have a significant impact on the structure and design of the UI layer.

I don't have any suggestions for how to build such a framework, but I would encourage you to play around with a few existing frameworks to see how they are designed, what you like about them, and what ideas to avoid.

For just one example, see the difference between managing the event loop entirely by hand with Win32[1] and using "signals and slots" in Qt[2]. There is a lot more to UI frameworks than this, and they vary on many more aspects.

- [1] https://docs.microsoft.com/en-us/windows/win32/winmsg/using-...

- [2] https://doc.qt.io/qt-5/signalsandslots.html


👤 raphlinus
http://www.cmyr.net/blog/gui-framework-ingredients.html has a bunch of what you'll need to know about building a GUI from scratch, especially if you're interested in any of the "hard parts" rather than making a toy. It's Rust rather than C++ but many of the principles are similar.

Other than that, I do recommend the immediate mode GUI approach if you're writing everything yourself, as it's the lowest overall system complexity of all the approaches. It has a number of drawbacks, and things don't abstract/compose as easily as a standard object-oriented retained, or a newer React/SwiftUI approach, but exposing the raw parts has its upsides.


👤 em3rgent0rdr
Rust world really needs a GUI...would be great if you helped out making a GUI for Rust: https://www.areweguiyet.com/

There is a start of a native Rust GUI which you could contribute to: https://github.com/linebender/druid


👤 smaddox
I highly recommend watching Casey Muratori's presentation on immediate mode GUIs, and his Handmade Hero series (links below).

https://caseymuratori.com/blog_0001

https://handmadehero.org/


👤 loxias
> The dummy app itself will be less about forms but more about data representation, e.g. an audio editor or a node-based system, where data should be updated and visualized in real time, and everything should feel responsive.

Would you be interested in a 'no restrictions, informal' collaboration?

I have little to no experience writing GUIs, but your "dummy apps" sound to me like the sorts of things I could populate the 'guts' of, to make useful.

For instance, I work a lot with audio signal processing, have considerable experience in that area, and am "half-assedly" (low priority side project) writing tools that would benefit from a GUI.

My email is on my profile.


👤 jagger27
I find the SerenityOS userland code base quite approachable. It's all written in C++.

👤 elcritch
I've been enjoying hacking on Fidget as a side project! It's inspired by Figma and is written in pure Nim with an OpenGL backend. Previously I'd been dabbling with ImGui, but wanted something with an efficient event loop driven renderer. It's enjoyable writing in a compact language that's fast and provides memory management.

Here's my fork of Fidget: https://github.com/elcritch/fidget

I've uploaded a few youtube samples: https://www.youtube.com/playlist?list=PLfEcHAJujZRlloKeDj6iK...

Based on what you're asking about you might be interested in following an example where I tied in Nim's async system into Fidget: https://github.com/elcritch/fidget/blob/devel/tests/progress...


👤 hawski
I would only like to urge you to think about accessibility. There are many custom GUI libraries out there, but almost all of them are made without thinking about accessibility. It kind of forces certain architecture, which may be hard to fit later. A11y APIs expose widgets in form of a tree.

I thought about writing a cross platform GUI toolkit, that would start from being a cross platform accessibility library.


👤 bitwize
Yeah. Don't.

GUI frameworks are like cryptography: you never want to roll your own. You will spend endless time implementing all the widgets a typical UI framework has, tweaking it until it feels kinda right, and even then they won't feel totally right until you've done extensive user testing and acted on the resultant feedback. Hundreds or thousands of hours of work for something that won't be as good as Windows, macOS, or Qt.

And I haven't even gotten started on internationalization or accessibility! Ohohohoho, boy.

There's a reason why the best (only good, really) UI framework is proprietary to a large, multi-trillion-dollar company.

In conclusion, just use your OS's native framework or one of the half-decent ones for Linux if you're working on Linux.


👤 phtrivier
If you have a mostly 2d UI in mind, you might to from something even simpler than opengl, like SDL or raylib - anything that lets you out pixels on a screen.

My personal experience is that starting developing in opengl always ends up wasting hours getting the right libs installed to get potentially full 3d GPU acceleration - which might be beyond the point if you want to draw stuff.

Casey muratorri is spot on in saying that not having a single, simple, unniversal and basic API to "open a window and draw pixels" is what we lost the most during the 90s.

Anyway, try to bypass the not-interesting-to-you parts, and have fun !


👤 throwaway2037
I cannot believe that no one has mentioned HTML Canvas with JavaScript. I'm no fan-boi/gurl for JavaScript, but you can do some crazy and amazing things with HTML Canvas in a modern web browser. Plus, "everyone" seems to think that TypeScript is a pretty great advance on JavaScript, by adding a bunch of useful things, like stricter types. As an added bonus, it's easy to share the results with others -- all they need is a browser.

👤 someweirdperson
First, you open a port to $DISPLAY...

xlib is quite a pleasure to use though, and it probably doesn't qualify as a "framework" that you don't want to use.


👤 worewood
I have tried to make bindings for GTK in Go way when its C interface didn't even support callbacks (so I used polling to capture events). Didn't go too far because there was a lot of repetitive work involved, but learned a lot in the process.

If you see yourself doing something 3+ times, automate it early!


👤 jazzfool
There is no right way to design a GUI library, so ignore the people that insist you read a book and follow the paradigms it mentions to a T. In fact, we really need less of those OOP GUI libraries right now. Definitely try poke around with reactive, etc.

👤 AussieWog93
I'd recommend actually building something with Dear ImGui (IMO, the best GUI framework in existence by a country mile). Merely reading about the differences between retained and immediate mode cannot do justice to the paradigm.

👤 4silvertooth
I think you should checkout www.juce.com framework github https://github.com/juce-framework/JUCE.

👤 heroku
Can someone comment on how https://github.com/aseprite/aseprite/ works.

👤 codr7
I'm keeping an eye on Skia to try out some vector based UI ideas I've been marinating for a while.

👤 svilen_dobrev
think about.. the various "hierarchies" / aspects / of the relations of the things in it. Event-passing is one ; Containment (x part-of y) is another ; Visual overlap yet another (now that depends on point of view) ; ... there are more.. depending on the purpose.

👤 ozim
Start with Bresenham's line algorithm :) if you want to go with "from scratch".

👤 imachine1980_
i recommend opengl for this instead of trying whit GUIs, you could make easy small simulations and shot in your foot whit rendering pipelines fast and easy, opengl resource are all over the place, good luck.

👤 scott01
Super! Thanks everyone for your answers. A lot of things to explore!

👤 nikolqy
Yikes. Just use Java or like C#. They perform just as good, if not better than C++ since with C++, you gotta do some things a very specific way to make it work. If anything, use the QT framework. That seems to be the biggest one for C++.