Learn Wayland by writing a GUI from scratch
gaultier.github.io
gaultier.github.io
Discussion: https://news.ycombinator.com/item?id=36153237 (638 points | 4 months ago | 146 comments)
From that link I also learned about lobste.rs which is also new (and interesting!) to me. Now I need to figure out a way to get an invite…
Could a kind soul please send me an invite to lobste.rs as well?
This book is nice if you want to:
- Understand Wayland itself
- Write applications without being dependent on GUI frameworks
- Write a compositor yourself
It's author is Drew DeVault.
Are there plans to do the same on the original site? The print button didn't work for me.
Now I haven't written any non-CLI GUI Linux applications in C. I once played with the Qt IDE. I feel it is pretty difficult stuff!
I think dbus is also really interesting too.
This causes me to think of the success of Nodejs and how it abstracts async and makes it approachable to anyone. Rather than pointers in C you have JavaScript object literals.
The most complicated GUIs I created were with Swing in Java and JavaScript.
Can someone more knowledgeable tell me what is GPU accelerated with Wayland? Is there a bitblit operation uses by compositor? And how would you write a high performance GUI that is maintainable. I'm aware Blink/Chromium uses Skia which I presume is accelerated.
In my JavaScript visualisation experiments with canvases - the page has started to slow down because I'm doing stuff on the main thread.
See this example - scroll down and you'll see a process visualiser and scroll down further and there's a graph. I'm doing parsing on the main thread https://replit.com/@Chronological/Processes3#index.html
I feel this would be so much harder to build in C.
I am kind of following the trends in GUI rendering tech - I am curious how you support rendering lists of hundreds of thousands of items without expensive update costs. The perennial react performance problem.
I'm following the approaches taken by Tauri and Rust desktop app designs. Looking for a silver bullet.
It's protocols which handle the communication between GUI toolkits your desktop manager (e.g. make new windows, resize windows, scaling, etc.) and how to connect to the GPU driver.
I.e. wayland isn't GUI technology it's a level below it.
So on systems using Wayland every GUI toolkit, including Skia, uses Wayland internally.
Also Wayland is _only_ protocols, so questions like "is window composition GPU accelerated" are implementation details of the specific compositor (through yes in general they are).
This is also on of the differences with X. Another one is X had a bunch of features sprinkled in which belong to the space of GUI toolkits (most of which had been abandoned by most software long before Wayland become relevant). Wayland is more cleanly designed wrt. to this aspects.
In contast, X was born before os had anything like dma-buf. X has all kinds of tools for drawing.
There's a lot griping about how Wayland isn't a monolithic server, how different compositors have to reimplement base capabilities and how this could lead to incompatibilities or different capability sets. Personally I think the fear uncertainty & doubt is overblow (open progress and possibility trumps conservative consistency), but I think what's technically interesting about how Wayland compositors work is that the Wayland design leaves so much more to the OS & client than X did. It makes it much more feasible to make a new compositor, since really Wayland is just a buffer manager, for os buffers, allocated by clients. This reinforces, to me, your proposition that Wayland is much more clean, by having to invent so very much less than X had to invent (and it truly had to, there we're not good os level constructs to use, the time).
Implementation detail.
>how different compositors have to reimplement base capabilities
Implementation detail
If people wanted they could make a monolithic server. They could make window management happen by a different process that could be swapped out.
I wish Wayland was architected around a state-synchronization model instead of being event-driven. It'd be extremely difficult to port client toolkits and would ultimately fail to attract adoption, of course, but you'd end up with a more resilient system overall, and one that could be a bit more implementation-agnostic.
Wayland will probably be amazing like many of other technologies I've ever disliked in the past (Some of them still seem to suck though!) but right now it's still effectively brand new on the general user scene.
X is a protocol too. Xorg isn't, it's an implementation. But there can be (and have been) others.
window = make_stupid_simple_undecorated_window(x, y, w, h);
paint_window(window, some_image_buffer);
block_forever();The main difference from CLI is that GUI works reacting to messages, even for (re)painting. Once you get that, the rest falls into place. This is usually implemented with object-oriented libraries, because it's the kind of application where OOP shines. But it's not mandatory.
Oh, and your app should also respond to move, change workspace, minimize... messages.
It is a nice approach to learn how things work, but not a recommended approach for building anything useful.
A couple examples of fragile code, so my comment is a little constructive:
- I truly dislike the cstring_len macro, which sounds like strlen yet its semantics are completely different.
- The wayland_display_connect function returns EINVAL or an fd. Both are positive integers. It should instead return -EINVAL.
- The functions benefit from more comments, because they do a lot and are not factored to smaller, more composable units.
- wayland_handle_message should be refactored so it's a simple switch that operates on constants, and ideally delegates to other functions.
- Probably outside of the scope of a simple article, but all the buffer boilerplate should be simplified by using a buffer structure that holds pointer, cursor and capacity, to make the code much more readable.
Is that actually possible? Opcodes by themselves are not unique, and the object IDs are right now assigned at runtime (I can’t tell if that’s actually necessary).
Or maybe return -1 and set errno? I haven't seen many C programs that return negative errnos (excepting the linux kernel which uses negative errnos internally).
It's lazy and quite ignorant to criticize teaching material because it doesn't cover all possible corner cases, and because it doesn't account for a reader that just wants to copy the code without understanding it.
The topic is Wayland, not C code hardening techniques for internet facing services. Quit being an obnoxious pedant.
But this is not production code, and shouldn't be read this way.
In my opinion the writer quite clearly establishes that this code and methodology is only intended to be illustrative of the broader subject, which is: how Wayland works.
And inasmuch as it is illustrative, the very many exploits it shows are explicitly available, is a root note of its value. This author knows whats up.
You should probably assert
#ifdef NDEBUG #error #endif
In your source code if your code assumes that assertions will never be disabled.
I assume assert also checks conditions at runtime?
assert(--index >= 0);