We'd be at the same spot, single-header files are still useful.
A single-header file is not a 'full-sized' library compressed into one file it's codebase is designed to actually be minimalist. Many libraries have single files that are the same size as their alternative single-header.
I wonder where we'd be if we'd stopped relying on system packages to provide dependencies for C / C++. It is positively miserable to have to pollute your system when a codebase written in Go / Rust / your favourite modern language Just Works out of the box.
With a central, curated, audited package repository where publishing rights are given to absolutely everyone then supply chain attacks in C and C++ would be even easier.
Windows is no excuse, because many of "single-header C library" sinners are UNIX only folks, targeting only UNIX platforms.
For me it only reveals lack of willingness to learn how to use their tools.
I learned how to use C and C++ build systems at the age of 12 years old, when most of the information was on libraries, or whatever folks down at computer club could explain.
In a computing landscape much more fragmented than it is today?
Do you think combining Windows and UNIX is hard? Try on the glory days of 16 bit home computers.
Here we are in the age of information, and some people couldn't be less bothered.
Haven't worked with it much yet, not really my point either. They were talking about OS package managers, most likely the typical Linux package managers, and so did I.
Most of those are for installing applications, not system-wide C library source distributions (e.g. you'll need to figure out the path of the source and header files in build scripts since there's no standard location for that on Windows).
The closest thing to a C/C++ package manager standard on Windows is probably vcpkg: https://vcpkg.io/en/
I realize you asked sarcastically, but as of relatively recently WinGet is shipped by default with the latest versions of Windows 10 and in Windows 11. [1]
on both cases, not having a default package manager shipped caused zero adoption attrition, I mean, besides the attrition of needing a non-standard package to begin with.
IMHO it is though. I have a windows VM I rarely use and tried using a package manager at some point, but end up not succeeding until winget was part of the system and was a no-brainer.
It was only partially sarcastic (yeah that didn't communicate at all, bad habit on my end), I had googled them but didn't quite understand the winget situation at glance. Thanks for the answer, actually appreciated!
I don't know why you're being downvoted, but distributions for Windows would be really popular. A server distribution of Windows would help its adoption a lot.
Since you're using C99 as the base C version, why not use the fixed-width types from stdint.h (int32_t, int64_t, ...)?
You can still typedef those to i32, i64 shortcuts etc, but I would try to avoid this in libraries since it might collide with user typedefs of the same name - or at least try to avoid it in the public API declarations.
AFAIK the STB headers are on C89 mainly because nothings likes to use VC6 as C IDE.
E.g. if you depend on other C99 features anyway, including stdint.h is fine, also on MSVC.
PS: FWIW I use stdint.h types in the Sokol headers since around 2017 and never heard complaints from users, with the supported compilers being MSVC, GCC and Clang.
I personally use `_MSC_VER >= 1600`, so it's since Visual Studio 2010 from April 2010. Built-in types like __int32 from before then may be used as well.
Thanks for the advice, I'm a little worried about breaking compatibility with compilers that don't support stdint. But if it's standard for C99 thing then sure.
I just roll my own for this because I don't need all the functionality, and generally find such cross-platform libraries to only really test on Linux, and it's too much of a hassle.
It depends whether you're compiling in 32-bit or 64-bit mode, MSVC has two different modes and there are different versions of MinGW for 32-bit and 64-bit
I'm not sure that issue would be caught by ordinary testing. It will implicitly cast into long long, so it might make little or no difference in this case.
A lot of people use i64 in the global namespace, so this will affect later code. It's basically `#define true false`. When I consider a library I will do a quick sniff test to look for very obvious mistakes, at which point I won't look further.
You could support mobile platforms as well. IIRC, even if Android allows creating only one window per activity, this behavior can be easily mapped on the abstraction that you provide.
I love single header libraries and I like the idea here of taking care of one necessity well. It seems like good modularity all around.
A quick heads up, the micro UI emscripten example doesn't work on chrome or firefox. The error is: DrawElements doesn't actually prepareClientAttributes properly.
The one big downside I see is that if you want to actually work on the library itself, it's a pain to have to re-compile the entire thing every time you change something.
Nuklear (https://github.com/Immediate-Mode-UI/Nuklear) uses separate files with a deploy script that combines them all into a single header; I think that approach is quicker for iterating on the code.
Sure, but the library is also relatively small, so it compiles quickly.
Although if you want to you can compile it on its own.
It's also possible to compile it on its own using `gcc -c -x c -D RGFW_IMPLEMENTATION RGFW.h`
Nuklear is not a true single-header style library, it only uses that as a format. The difference is that the design is far less compact and lightweight than a stb-style library.
I'm pretty sure GLFW has some files that are nearly the same size as RGFW, for example.
It is a single-header library in terms of the format, yes. But it is also not designed to be a single-header library, unlike an STB-style library.
Nuklear is a full-sized library that can be compiled into and used as one file. However, RGFW and STB are designed to be lightweight and minimalistic. That's the distinctive part of single-header libraries, also known as STB-style libraries.
To be clear, I don't mean this to hate on Nuklear, it's a cool UI library, but its design doesn't match the single-header format.
What is this supposed to be telling me? This also looks like it was multiple files concatenated together because there are multiple different header guards throughout the file.
Have you actually tried? This is 287 KB of C. MSVC on computers from 15 years ago will compile C at about 60 MB/s. I'm skeptical this is actually a problem.
SQLite is distributed as a single 6 MB .c file and compiles in ... 0.1 seconds.
That may be true for extremely simple source code, but it's almost too good to be true. Your number sounded so impressive that I tried with gcc (12.2) on my Linux VM. With -O0, it takes around 27s, with -O2 it's 1m07s.
With -E (only preprocess) we are at around 0.320s for the 260K lines of sqlite3.c. Which makes sense, 1M lines/s for the preprocessor and maybe also the AST should be doable (that may be where you got your 60MB/s number from). But compiling is something else.
MSVC may be faster here or not, I haven't tested it.
A more modern machine (mine is a i5-7600K from 2018) may be 2x or more faster, and running on multiple threads will speed up the build as well.
(that may be where you got your 60MB/s number from)
It's not that. I think I messed up and the 0.1 seconds was tcc and msvc was 1 or 2 seconds. Nothing was 27 seconds. Try tcc, even though you are in a VM it should be very fast as a baseline for what's possible.
The point is that some people talk about single header files being slow are really saying "what if". C is incredibly fast to compile and the slow parts are the overhead from each compilation unit and the optimizers.
287 KB of source code added to a compilation unit is nothing in the modern era. Not only that, but you can just choose to put a lot of them in the same compilation unit and not touch it again.
Every time I've used single file header libraries it makes things simple and fast. I'm not going to change them so dumping them all into a single compilation unit is fine.
I like simple code written in C, but when does this "single-header" nonsense stop? C has super nice and simple modularization via the classical .h/.c split which ensures fast compilation, proper encapsulation, no instruction bloat via creating multiple instances for all functions.
The issue if if you have many such libraries and any change to the implementation forces recompilation of everything. Maybe not such a big deal for such small libraries, but an annoying trend IMHO.
> no instruction bloat via creating multiple instances for all functions.
This makes me think that you're using single-header libraries wrong. These kind of libraries usually require you to do something special prior to including it to get the actual code and you must do it only in ONE file.
For example, you'd #define RGFW_IMPLEMENTATION before #include rgfw.h in exactly ONE .c. If you need the header in other files, you do NOT define RGFW_IMPLEMENTATION and no code will be produced.
I actually agree with you that single-header libs are often not ideal. They're kind of neat in concept: just copy paste and done!
But after being burned a few times by naming or linking conflicts or you cloned your .c and forgot to remove the #define and now you have two implementations or having to debug any BSS/DATA/TEXT issues (because now lib and user code end up in the same .o and the linker can't do its magic for your esoteric architecture), I just took the habit of always manually creating a matching .c that only contains:
Well for one you're able to easily use macros to customize features you want and don't want. Plus "forcing me to figure out the specific XYZ_IMPLEMENTATION" is a big of a weird compliant. You could say the same thing about linking a library. Besides, it's not hard to figure out and is usually one of the first lines of the file.
The single-header format also gives you MORE ways to compile the library and control which features to use or not use.
I can't figure out why anyone would call it 'nonsense'. The definitions and functions have to be together, they may as well be a single file separated by a preprocessor definition.
Include the header where you want the definitions. Include the header and use the preproccesor definition in the compilation unit you want the functions in. Done.
There is no speed issue here. It would take 100x the C to make a difference and it's actually going to be much faster and simpler to put a lot of single file libraries into one compilation unit. I always wonder if the downsides are theoretical or if people are really doing what I've been doing and still have a problem with it.
X11 is fine. It's mostly just Video Games that need an alternative. It'd be nice if there was a "pause X11 video card control and give exclusive access to a single application." Then there's no need to care.
This actually doesn’t work with modern expectations.
Modern games are expected to work in multi-monitor setups and render in “borderless windowed” mode, so you can alt-tab out to multitask, or have a comms overlay. Single monitor single process gaming still happens, but a good 85% of setups (according to the Steam Hardware Survey) are not that. There are five games I know or that actually handle multimonitor natively of the hundreds I’ve played. So we need some form of cooperative multitasking for graphics with the window manager.
Modern good games are not expected to "render in “borderless windowed” mode, so you can alt-tab out to multitask"
Really bad games with slow multiplayer match making lobby and tiresome repetitive gameplay and bad UX where you need to look most of the actual game information on a fan wiki, or triple A games where you have to login and enter credit card information on a "launcher"... those are the ones you expect to "render in “borderless windowed” mode, so you can alt-tab out to multitask". Good riddance.
X11 is utterly broken for multi-monitor setups with different resolutions at different scales (e. g. builtin laptop screen @1.25x, external display at 1x or some variation of that). With high resolution screens (e g. 4k at only 27"), that setup is not uncommon anymore.
(Wayland is broken in very many other ways, though, so you trade one evil for... 5 others).
X was a very well designed system IMHO that could be evolved via extensions (e.g. how compositing was added etc.). It is sad that few people work on it anymore to fix such issues.
X isn't opinionated enough, and Wayland is even worse. While X has labels like "substructure redirect override" that in practice means "bypass the window manager" and tries to theoretically support multiple window managers, Wayland barely even knows what a window is!
Correction: Xorg doesn't have good support for this. I don't think there's an extension for it in the protocol either, but one could be created - just as it has for Wayland. Apps that don't support the extension should be scaled by the compositor as usual.
X11 has a reasonably solid core, though, while Wayland does not.
- Better API design
- Not being experimental after 11 years
I think that Wayland actually has some steps in the right direction, but overall I don't think it's actually a very good alternative. It's way more low-level than X11 and a lot of higher level features, like window decorations, are not even officially supported.
Yeah, I've been looking for a minimal SDL alternative for a long time and I was really excited reading through this as that solution, but the lack of Wayland support is a huge dealbreaker for me.
Are there any good minimal windowing utilities that support Wayland? SDL does a lot I don't need and I try to maintain minimal dependencies. I suppose I could just use glfw & libsoundio, haven't tried that yet.
Every time I see a "single-header C library", I wonder to myself where we'd be if only Windows had a proper package manager.
(Especially since that'd force the POSIX world to de-fracture itself too.)
We'd be at the same spot, single-header files are still useful.
A single-header file is not a 'full-sized' library compressed into one file it's codebase is designed to actually be minimalist. Many libraries have single files that are the same size as their alternative single-header.
I wonder where we'd be if we'd stopped relying on system packages to provide dependencies for C / C++. It is positively miserable to have to pollute your system when a codebase written in Go / Rust / your favourite modern language Just Works out of the box.
With a central, curated, audited package repository where publishing rights are given to absolutely everyone then supply chain attacks in C and C++ would be even easier.
Windows is no excuse, because many of "single-header C library" sinners are UNIX only folks, targeting only UNIX platforms.
For me it only reveals lack of willingness to learn how to use their tools.
I learned how to use C and C++ build systems at the age of 12 years old, when most of the information was on libraries, or whatever folks down at computer club could explain.
In a computing landscape much more fragmented than it is today?
Do you think combining Windows and UNIX is hard? Try on the glory days of 16 bit home computers.
Here we are in the age of information, and some people couldn't be less bothered.
Nope, most people using it know how to link and compile libraries. :)
Maybe, but those providing it apparently not.
> a proper package manager
Those are a thing? Wasn't aware.
Isn't the one from Rust pretty good?
Haven't worked with it much yet, not really my point either. They were talking about OS package managers, most likely the typical Linux package managers, and so did I.
We'd be in exactly the same place because nobody wants to use an OS-dependent package manager for an OS-agnostic project.
I don't know if you noticed but no modern languages use Linux packages to provide dependencies, because that obviously sucks balls for many reasons.
scoop? chocolatey? pacman in msys2? winget?
Most of those are for installing applications, not system-wide C library source distributions (e.g. you'll need to figure out the path of the source and header files in build scripts since there's no standard location for that on Windows).
The closest thing to a C/C++ package manager standard on Windows is probably vcpkg: https://vcpkg.io/en/
Remind me please, which of these is shipped with a default Windows install?
I realize you asked sarcastically, but as of relatively recently WinGet is shipped by default with the latest versions of Windows 10 and in Windows 11. [1]
But why is being installed by default important?
[1] https://www.petergirnus.com/blog/how-to-use-windows-package-...
It's an adoption barrier.
I know very non-technical people who use Chocolatey for acquiring ffmpeg.
meh. it's not.
If you are convincing people to run commands to install packages:
- they care about trust, they will already have their package manager from the ecosystem they trust (which should be msys+pacman on windows, btw)
- they couldn't care less and will trust your `curl | bash` or `Invoke-RestMethod -Uri http://hacker.com/totallysafe.exe`
on both cases, not having a default package manager shipped caused zero adoption attrition, I mean, besides the attrition of needing a non-standard package to begin with.
IMHO it is though. I have a windows VM I rarely use and tried using a package manager at some point, but end up not succeeding until winget was part of the system and was a no-brainer.
Too many possibilities made me choose none.
It was only partially sarcastic (yeah that didn't communicate at all, bad habit on my end), I had googled them but didn't quite understand the winget situation at glance. Thanks for the answer, actually appreciated!
The same that shipped with a default UNIX install.
I don't know why you're being downvoted, but distributions for Windows would be really popular. A server distribution of Windows would help its adoption a lot.
Not sure whether this is tested on Windows at all. I opened the header and immediately found this `typedef signed long i64`, i.e. i64 is actually i32.
This is strange because C99 has stdint.h so we don't need to use "short/long/long long/long long long" nonsense anymore.
I test Windows mainly with MINGW, that might be an issue with MSVC. Feel free to report the issue on the github repository.
I'm pretty sure windows uses "long" for 64 bit but linux uses "long long" for 64 bit
Since you're using C99 as the base C version, why not use the fixed-width types from stdint.h (int32_t, int64_t, ...)?
You can still typedef those to i32, i64 shortcuts etc, but I would try to avoid this in libraries since it might collide with user typedefs of the same name - or at least try to avoid it in the public API declarations.
I use those by default although I read that MSVC's support for those are iffy. I'm pretty sure STB does the same thing for the same reason.
Source: https://handmade.network/forums/articles/t/7138-how_to_write...
Since around Visual Studio 2015 you're fine.
AFAIK the STB headers are on C89 mainly because nothings likes to use VC6 as C IDE.
E.g. if you depend on other C99 features anyway, including stdint.h is fine, also on MSVC.
PS: FWIW I use stdint.h types in the Sokol headers since around 2017 and never heard complaints from users, with the supported compilers being MSVC, GCC and Clang.
Since around Visual Studio 2015 you're fine.
I personally use `_MSC_VER >= 1600`, so it's since Visual Studio 2010 from April 2010. Built-in types like __int32 from before then may be used as well.
Oh, I wasn't sure if that was you :)
Thanks for the advice, I'm a little worried about breaking compatibility with compilers that don't support stdint. But if it's standard for C99 thing then sure.
> I'm pretty sure windows uses "long" for 64 bit but linux uses "long long" for 64 bit
Windows long is 32bit even on 64bit CPUs.
Linux long is arch dependent and is 64bit on x64, 32bit on x86.
long long is always 64bit on both platforms.
Okay, thank you.
It's just that the #if checks for the MSVC compiler, not for Windows as a platform. And on that compiler you will never have LP64, but LLP64: https://en.wikipedia.org/wiki/64-bit_computing#64-bit_data_m...
I just roll my own for this because I don't need all the functionality, and generally find such cross-platform libraries to only really test on Linux, and it's too much of a hassle.
Yes, because MSVC may or may not have stdint.h
It does. Why do you think it might not?
> I'm pretty sure windows uses "long" for 64 bit but linux uses "long long" for 64 bit
other way around
It depends whether you're compiling in 32-bit or 64-bit mode, MSVC has two different modes and there are different versions of MinGW for 32-bit and 64-bit
For MSVC, long is 4 bytes: https://learn.microsoft.com/en-us/cpp/cpp/fundamental-types-...
I'm not sure that issue would be caught by ordinary testing. It will implicitly cast into long long, so it might make little or no difference in this case.
A lot of people use i64 in the global namespace, so this will affect later code. It's basically `#define true false`. When I consider a library I will do a quick sniff test to look for very obvious mistakes, at which point I won't look further.
:( That's disappointing, but I understand.
This was added to raylib as a backend recently: https://github.com/raysan5/raylib/releases#:~:text=RGFW
You could support mobile platforms as well. IIRC, even if Android allows creating only one window per activity, this behavior can be easily mapped on the abstraction that you provide.
That's something I plan on looking into at some point. I'm unsure if I want that in the main version or a separate branch for embedded devices.
It's low priority though because my main focus is desktop applications.
sokol_app.h has mobile support
I love single header libraries and I like the idea here of taking care of one necessity well. It seems like good modularity all around.
A quick heads up, the micro UI emscripten example doesn't work on chrome or firefox. The error is: DrawElements doesn't actually prepareClientAttributes properly.
The one big downside I see is that if you want to actually work on the library itself, it's a pain to have to re-compile the entire thing every time you change something.
Nuklear (https://github.com/Immediate-Mode-UI/Nuklear) uses separate files with a deploy script that combines them all into a single header; I think that approach is quicker for iterating on the code.
Sure, but the library is also relatively small, so it compiles quickly. Although if you want to you can compile it on its own.
It's also possible to compile it on its own using `gcc -c -x c -D RGFW_IMPLEMENTATION RGFW.h`
Nuklear is not a true single-header style library, it only uses that as a format. The difference is that the design is far less compact and lightweight than a stb-style library.
I'm pretty sure GLFW has some files that are nearly the same size as RGFW, for example.
Why do you claim Nuklear is not a "true single-header style library"? And who gets to say what that even means?
It is a single-header library in terms of the format, yes. But it is also not designed to be a single-header library, unlike an STB-style library.
Nuklear is a full-sized library that can be compiled into and used as one file. However, RGFW and STB are designed to be lightweight and minimalistic. That's the distinctive part of single-header libraries, also known as STB-style libraries.
To be clear, I don't mean this to hate on Nuklear, it's a cool UI library, but its design doesn't match the single-header format.
How is it not designed to be a single-header library? The README even directly states "Single-header library".
How is it not designed to be lightweight and minimalistic?
How do you think the design differs from your idea (which is what exactly?) of a "single-header format"?
https://github.com/SasLuca/glfw-single-header/blob/master/ex...
What is this supposed to be telling me? This also looks like it was multiple files concatenated together because there are multiple different header guards throughout the file.
Have you actually tried? This is 287 KB of C. MSVC on computers from 15 years ago will compile C at about 60 MB/s. I'm skeptical this is actually a problem.
SQLite is distributed as a single 6 MB .c file and compiles in ... 0.1 seconds.
That may be true for extremely simple source code, but it's almost too good to be true. Your number sounded so impressive that I tried with gcc (12.2) on my Linux VM. With -O0, it takes around 27s, with -O2 it's 1m07s.
With -E (only preprocess) we are at around 0.320s for the 260K lines of sqlite3.c. Which makes sense, 1M lines/s for the preprocessor and maybe also the AST should be doable (that may be where you got your 60MB/s number from). But compiling is something else.
MSVC may be faster here or not, I haven't tested it.
A more modern machine (mine is a i5-7600K from 2018) may be 2x or more faster, and running on multiple threads will speed up the build as well.
What exactly did you try to compile and how?
sqlite3, if you read carefully again.
(that may be where you got your 60MB/s number from)
It's not that. I think I messed up and the 0.1 seconds was tcc and msvc was 1 or 2 seconds. Nothing was 27 seconds. Try tcc, even though you are in a VM it should be very fast as a baseline for what's possible.
The point is that some people talk about single header files being slow are really saying "what if". C is incredibly fast to compile and the slow parts are the overhead from each compilation unit and the optimizers.
287 KB of source code added to a compilation unit is nothing in the modern era. Not only that, but you can just choose to put a lot of them in the same compilation unit and not touch it again.
Every time I've used single file header libraries it makes things simple and fast. I'm not going to change them so dumping them all into a single compilation unit is fine.
I'm aware of the errors for the micro UI (on the web), it's something I plan on looking into soon!
Thanks :)
I like simple code written in C, but when does this "single-header" nonsense stop? C has super nice and simple modularization via the classical .h/.c split which ensures fast compilation, proper encapsulation, no instruction bloat via creating multiple instances for all functions.
Try putting GLFW's source code into one file and then compile it. That will take at least a few seconds, RGFW compiles in less than a second.
Where's the bloat? :)
https://github.com/SasLuca/glfw-single-header/blob/master/ex...
The issue if if you have many such libraries and any change to the implementation forces recompilation of everything. Maybe not such a big deal for such small libraries, but an annoying trend IMHO.
> no instruction bloat via creating multiple instances for all functions.
This makes me think that you're using single-header libraries wrong. These kind of libraries usually require you to do something special prior to including it to get the actual code and you must do it only in ONE file.
For example, you'd #define RGFW_IMPLEMENTATION before #include rgfw.h in exactly ONE .c. If you need the header in other files, you do NOT define RGFW_IMPLEMENTATION and no code will be produced.
Well, I do not use them at all. But I agree that this mechanism would avoid the additional copies. I have seen other single-header libraries though...
In any case, forcing me to figure out the specific XYZ_IMPLEMENTATION for each library is less user friendly that just proving a .c and .h file.
I actually agree with you that single-header libs are often not ideal. They're kind of neat in concept: just copy paste and done!
But after being burned a few times by naming or linking conflicts or you cloned your .c and forgot to remove the #define and now you have two implementations or having to debug any BSS/DATA/TEXT issues (because now lib and user code end up in the same .o and the linker can't do its magic for your esoteric architecture), I just took the habit of always manually creating a matching .c that only contains:
Well for one you're able to easily use macros to customize features you want and don't want. Plus "forcing me to figure out the specific XYZ_IMPLEMENTATION" is a big of a weird compliant. You could say the same thing about linking a library. Besides, it's not hard to figure out and is usually one of the first lines of the file.
The single-header format also gives you MORE ways to compile the library and control which features to use or not use.
I am not say it is hard. But I find having a .c/.h pair more useful and easier to work with.
No lol
Because looking up a macro name for each library is easier than adding a c file to your makefile? You could still always do
and this would still be nicer thanI can't figure out why anyone would call it 'nonsense'. The definitions and functions have to be together, they may as well be a single file separated by a preprocessor definition.
Include the header where you want the definitions. Include the header and use the preproccesor definition in the compilation unit you want the functions in. Done.
There is no speed issue here. It would take 100x the C to make a difference and it's actually going to be much faster and simpler to put a lot of single file libraries into one compilation unit. I always wonder if the downsides are theoretical or if people are really doing what I've been doing and still have a problem with it.
Too many script kiddies taking C for another scripting language.
> Wayland support is very experimental and broken
You and everyone else, RGFW, you and everyone else.
X11 needs a real alternative :(
Are you kidding? I started reading the X11 handbook series in the 1980s and now it's 2024 and I'm nearly finished, and you want to replace it? ;-)
X11 is fine. It's mostly just Video Games that need an alternative. It'd be nice if there was a "pause X11 video card control and give exclusive access to a single application." Then there's no need to care.
You just described X11's DRI (direct rendering infrastructure).
https://en.m.wikipedia.org/wiki/Direct_Rendering_Infrastruct...
This actually doesn’t work with modern expectations.
Modern games are expected to work in multi-monitor setups and render in “borderless windowed” mode, so you can alt-tab out to multitask, or have a comms overlay. Single monitor single process gaming still happens, but a good 85% of setups (according to the Steam Hardware Survey) are not that. There are five games I know or that actually handle multimonitor natively of the hundreds I’ve played. So we need some form of cooperative multitasking for graphics with the window manager.
Modern good games are not expected to "render in “borderless windowed” mode, so you can alt-tab out to multitask"
Really bad games with slow multiplayer match making lobby and tiresome repetitive gameplay and bad UX where you need to look most of the actual game information on a fan wiki, or triple A games where you have to login and enter credit card information on a "launcher"... those are the ones you expect to "render in “borderless windowed” mode, so you can alt-tab out to multitask". Good riddance.
X11 is utterly broken for multi-monitor setups with different resolutions at different scales (e. g. builtin laptop screen @1.25x, external display at 1x or some variation of that). With high resolution screens (e g. 4k at only 27"), that setup is not uncommon anymore.
(Wayland is broken in very many other ways, though, so you trade one evil for... 5 others).
X was a very well designed system IMHO that could be evolved via extensions (e.g. how compositing was added etc.). It is sad that few people work on it anymore to fix such issues.
X isn't opinionated enough, and Wayland is even worse. While X has labels like "substructure redirect override" that in practice means "bypass the window manager" and tries to theoretically support multiple window managers, Wayland barely even knows what a window is!
Wayland's scaling for 1.25x and even 1.5x is not so great either, though it is slowly going in the right direction with wp-fractional-scale-v1
Correction: Xorg doesn't have good support for this. I don't think there's an extension for it in the protocol either, but one could be created - just as it has for Wayland. Apps that don't support the extension should be scaled by the compositor as usual.
X11 has a reasonably solid core, though, while Wayland does not.
What do you expect from an alternative?
- Better API design - Not being experimental after 11 years
I think that Wayland actually has some steps in the right direction, but overall I don't think it's actually a very good alternative. It's way more low-level than X11 and a lot of higher level features, like window decorations, are not even officially supported.
Yeah, I've been looking for a minimal SDL alternative for a long time and I was really excited reading through this as that solution, but the lack of Wayland support is a huge dealbreaker for me.
Are there any good minimal windowing utilities that support Wayland? SDL does a lot I don't need and I try to maintain minimal dependencies. I suppose I could just use glfw & libsoundio, haven't tried that yet.
As far as I know, RGFW is the only minimal windowing of its kind. I guess I would suggest either targeting XWayland or using GLFW.
The Wayland API itself also really sucks to work with, even more so than Xlib....
But, RGFW's Wayland support will probably be improved in the future. :)
Rust has a lot of those small libs, my favorite is miniquad
https://crates.io/crates/miniquad
Other alternatives: pixels, minifb, softbuffer.
Sure, but none of these are true alternatives because they are missing a lot of features that libraries like GLFW or RGFW have.
(They may be good alternatives for certain use-cases)
Oh, just based on the README I assumed RGFW was more minimal than it actually is.
Minimal refers to the code itself.
GLFW's codebase is ~10MB while RGFW's is about ~300kb. But RGFW tries to support nearly everything that GLFW supports.
Yeah, my bad :)
GLFW has worked well for me.
Waylands problem is that to use it, you need code generation so the wayland backend kinda hard to design for a header only lib.
I've seen some interesting work in doing Wayland by hand:
https://gaultier.github.io/blog/wayland_from_scratch.html
I'd also look at the work done on minimal wayland projects like [foot](https://codeberg.org/dnkl/foot), which supports wayland well and seems to be written by hand (see: https://codeberg.org/dnkl/foot/src/branch/master/wayland.c)
I just have the Makefile do the code generation, it would be annoying for the user, but they can complain to Wayland if they don't like it.
Isn't SDL itself is quite minimal already? I mean, it is definitely not high-level in any sense of the word.
SDL provides..
..an image decoding library.
..an audio input/output library.
..a multi-channel audio mixer.
..ttf and rtf font rendering.
..networking.
..runtime shader cross-compilation
..its own entire graphics abstraction layer / API.
..its own shader language, shader compiler, and shader bytecode format.
I don't know at which point something becomes 'high level', but SDL is only 'minimal' if you use a subset of its functionality.
Not minimal in the sense of "just give me a window, a minimal event loop, and a GPU context/swapbuffers function".
Even then, that's what GLFW is designed to do, and it's entire source code is still far larger than RGFW's.